   Using a shader on a Sphere
  Hey guys.I was wondering how exactly I could use a shader to make something like this on a sphere. http://freespace.virgin.net/hugo.elias/models/p4_b.gif - I'm using hlsl with gamebryo and did it like this for a flat grid with a height map attached - to apply 4 different textures. But I'm unsure on how I'd go about it with a sphere that has elevated mountains on it etc.VS_OUTPUT VS(float4 inPos: POSITION, float2 inTex0: TEXCOORD0, float4 inNormal: NORMAL){    VS_OUTPUT Out;Out.Pos = mul(float4(inPos.xyz, 1.0f), WorldViewProj);Out.Normal = inNormal;    Out.TexCoord = inTex0 * 10;    Out.VecEye = normalize(inPos - float4(EyePos,1));    // Store the position of the untransformed vertex in the color    Out.Color = float4(1, 0, 0, clamp(inPos.z/50, 0, 1));    return Out;}float4 PS(VS_OUTPUT In) : COLOR{   float4 returnColor = 0;    float4 BlendBaseColor = tex2D(BaseSampler, In.TexCoord).rgba;    float4 BlendDarkColor = tex2D(DarkSampler, In.TexCoord).rgba;    float4 BlendDetailColor = tex2D(DetailSampler, In.TexCoord).rgba;    float4 BlendGlossColor = tex2D(GlossSampler, In.TexCoord).rgba;    float4 BlendGlowColor = tex2D(GlowSampler, In.TexCoord).rgba;    float4 BlendNormalColor = tex2D(NormalSampler, In.TexCoord).rgba;if(In.Color.a <= 0.05f)// Dirt{returnColor = lerp(BlendNormalColor, BlendGlowColor, In.Color.a * 20);}else if(In.Color.a >= 0.05 && In.Color.a <= 0.40)// Stone{returnColor = lerp(BlendGlowColor, BlendDetailColor, (In.Color.a - 0.05) * 3);}else if(In.Color.a >= 0.40 && In.Color.a <= 0.75)// Grass{returnColor = lerp(BlendDetailColor, BlendBaseColor, (In.Color.a - 0.40) * 3);}else if(In.Color.a >= 0.75 && In.Color.a <= 1.00)// Dirt{returnColor = lerp(BlendBaseColor, BlendNormalColor,  (In.Color.a - 0.75) * 4);}return returnColor;}Hope you understand my question. It's probably really simple to do it with a sphere but I can't get anything working.Thanks heaps,Scott.   
  I think I might try to make the question a little clearer possibly.I've been trying to texture a sphere like this one using a HLSL shader in gamebryo.I've procedurally built this sphere and created a spherical landscape on it with these functions.void Sphere::BuildSphere(){printf("Generating Spheres - Structure\n");int tDiv = this->m_NumSlices;int pDiv = this->m_NumStacks;float dt = (PI * 2) / tDiv;    float dp = PI / pDiv;for (int pi = 0; pi <= pDiv; pi++)    {   float phi = pi * dp;   for (int ti = 0; ti <= tDiv; ti++)   {  // we want to start the mesh on the x axis  float theta = ti * dt;m_Vertices.push_back(GetPosition(theta, phi, m_Radius));m_Normals.push_back(GetNormal(theta, phi));m_UVs.push_back(GetTextureCoordinate(theta, phi));   }    }for (int pi = 0; pi < pDiv; pi++)    {   for (int ti = 0; ti < tDiv; ti++)   {  int x0 = ti;  int x1 = (ti + 1);  int y0 = pi * (tDiv + 1);  int y1 = (pi + 1) * (tDiv + 1);m_Indices.push_back(x0 + y0);  m_Indices.push_back(x0 + y1);  m_Indices.push_back(x1 + y0);  m_Indices.push_back(x1 + y0);  m_Indices.push_back(x0 + y1);  m_Indices.push_back(x1 + y1);   }    }}void Sphere::AddLandScapeMirror(int iterations, float push){printf("Generating Spheres - Landscape\n");for( int i = 0; i < iterations; i++ ){NiPoint3 n = NiPoint3(RandomFloat(-1, 1), RandomFloat(-1, 1), RandomFloat(-1, 1));while( NiPoint3::VectorLength(n) >= 1 ){n = NiPoint3(RandomFloat(-1, 1), RandomFloat(-1, 1), RandomFloat(-1, 1));}for( unsigned int j = 0; j < m_Vertices.size(); j++ ){float d = n.Dot(m_Vertices[j]);// Good movement amount = 0.0005f//float movement = 0.0005f;if( d > 0 ){m_Vertices[j] += m_Vertices[j] * push;}else{m_Vertices[j] -= m_Vertices[j] * push;}}}}Everything builds and works fine in terms of, vertices, indices, normals, and texture uv's. When I apply a single texture of the sphere it works perfectly. The texture wraps around beautiful. But this is not how I want this project to work. Considering I have made the sphere have a landscape on it's surface, I want to be able to apply a brown texture for the raised bumps on the surface and a blue texture for the areas that are not raised as much on the surface.I've no clue how to even get a HLSL shader to do what I want here. On a project I finished the other week I made a simple shader to color a grid according to how high each vert was in the grid. This allowed me to have 4 different textures accross the gird. Checking to see how high a vertex was, then texturing that vertex the appropriate texture.My vertex and pixel shader looked like this in the grid exampleTerrain NSF// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION//// This software is supplied under the terms of a license agreement or// nondisclosure agreement with Emergent Game Technologies and may not // be copied or disclosed except in accordance with the terms of that // agreement.//// Copyright (c) 1996-2008 Emergent Game Technologies.// All Rights Reserved.//// Emergent Game Technologies, Chapel Hill, North Carolina 27517// http://www.emergent.netNSFShader Terrain{    "This shader is a simple example of warping a mesh"    "based on a sin() wave modulated by the AnimationTime"    // Attribute list    Attributes    {   Attrib_Float   AnimationTime   Artist 0.0  // Attrib_Point3EyePosArtist0.0    }    Global_Attributes    {Attrib_Point3EyePosArtist0.0,0.0,0.0    }    // Packing Definition    PackingDef PosNormUV0    {   PD_Stream   0  PDP_Position    0   PDT_Float3  PDP_Normal 3   PDT_Float3  PDP_TexCoord0   7   PDT_Float2    }    // Implementation    Implementation VS11_PS20    {   "This implementation is intended for hardware "   "that supports Vertex Shader v1.1 and Pixel Shader v2.0" // Requirements for this implementation   Requirements   {  Platform  = DX9  VSVersion = v3.0  UserVersion    = v0.0  PSVersion = v3.0  UsesNiRenderState   = true   } // Packing Definition it uses   PackingDef  PosNormUV0   // First pass   Pass Pass0   {  // Vertex shader program  VSProgram   "Terrain.hlsl" VS vs_3_0  // Vertex Shader constant map  VS_Constantmap  { CM_Defined WorldViewProj   WorldViewProj   0 CM_Attribute    AnimationTime 4   1   0 CM_GlobalEyePos53  }  PSProgram   "Terrain.hlsl" PS ps_3_0    // Sampler Base Texture  Sampler 0   BaseSampler  { TSS_Texture= NTM_Base TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }  // Sampler for Dark Texture  Sampler 1   DarkSampler  { TSS_Texture= NTM_Dark TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }    // Sampler for Detail Texture  Sampler 2 DetailSampler  {TSS_Texture= NTM_Detail TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }// Sampler for Gloss Texture  Sampler 3 GlossSampler  {TSS_Texture= NTM_Gloss TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }// Sampler for Glow Texture  Sampler 4 GlowSampler  {TSS_Texture= NTM_Glow TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }    // Sampler for Bump Texture  Sampler 5 BumpSampler  {TSS_Texture= NTM_Bump TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }    // Sampler for Normal Texture  Sampler 6 NormalSampler  {TSS_Texture= NTM_Normal TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }    // Sampler for Parallax Texture  Sampler 7 ParallaxSampler  {TSS_Texture= NTM_Parallax TSAMP_AddressU  = TADDR_Wrap TSAMP_AddressV  = TADDR_Wrap TSAMP_AddressW  = TADDR_Wrap TSAMP_MagFilter = TEXF_Linear TSAMP_MinFilter = TEXF_Linear TSAMP_MipFilter = TEXF_None  }}    }    }Terrain HLSLsampler2D BaseSampler : register(s0);sampler2D DarkSampler : register(s1);sampler2D DetailSampler : register(s2);sampler2D GlossSampler : register(s3);sampler2D GlowSampler : register(s4);sampler2D BumpSampler : register(s5);sampler2D NormalSampler : register(s6);sampler2D ParallaxSampler : register(s7);//---------------------------------------------------------------------------// Constants//---------------------------------------------------------------------------float4x4 WorldViewProj;float AnimationTime;float3 EyePos;//---------------------------------------------------------------------------// Vertex Shaders//---------------------------------------------------------------------------struct VS_OUTPUT{    float4 Pos : POSITION;    float4 Normal: NORMAL;    float4 Color    : COLOR;    float2 TexCoord : TEXCOORD;    float4 VecEye: TEXCOORD1;};VS_OUTPUT VS(float4 inPos: POSITION, float2 inTex0: TEXCOORD0, float4 inNormal: NORMAL){    VS_OUTPUT Out;Out.Pos = mul(float4(inPos.xyz, 1.0f), WorldViewProj);Out.Normal = inNormal;    Out.TexCoord = inTex0 * 10;    Out.VecEye = normalize(inPos - float4(EyePos,1));    // Store the position of the untransformed vertex in the color    Out.Color = float4(1, 0, 0, clamp(inPos.z/50, 0, 1));    return Out;}//---------------------------------------------------------------------------// Pixel Shaders//---------------------------------------------------------------------------float4 PS(VS_OUTPUT In) : COLOR{   float4 returnColor = 0;//Return Reset    float4 BlendBaseColor = tex2D(BaseSampler, In.TexCoord).rgba;    float4 BlendDarkColor = tex2D(DarkSampler, In.TexCoord).rgba;    float4 BlendDetailColor = tex2D(DetailSampler, In.TexCoord).rgba;    float4 BlendGlossColor = tex2D(GlossSampler, In.TexCoord).rgba;    float4 BlendGlowColor = tex2D(GlowSampler, In.TexCoord).rgba;    float4 BlendNormalColor = tex2D(NormalSampler, In.TexCoord).rgba;if(In.Color.a <= 0.05f)// Dirt{returnColor = lerp(BlendNormalColor, BlendGlowColor, In.Color.a * 20);}else if(In.Color.a >= 0.05 && In.Color.a <= 0.40)// Stone{returnColor = lerp(BlendGlowColor, BlendDetailColor, (In.Color.a - 0.05) * 3);}else if(In.Color.a >= 0.40 && In.Color.a <= 0.75)// Grass{returnColor = lerp(BlendDetailColor, BlendBaseColor, (In.Color.a - 0.40) * 3);}else if(In.Color.a >= 0.75 && In.Color.a <= 1.00)// Dirt{returnColor = lerp(BlendBaseColor, BlendNormalColor,  (In.Color.a - 0.75) * 4);}return returnColor;}Snipet Of the Shader in cppvoid ObjectShader::CreateTerrain(NiMeshPtr spMesh){// dirt, stone, grass, snowNiTexturingPropertyPtr spTerrainTexture = NiNew NiTexturingProperty("Data/dirt.bmp");//--------------------------------------Terrain Shaders In Use-----------------------------------------------spTerrainTexture->SetNormalMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/dirt.bmp"), 0));//0.75 - 1.00spTerrainTexture->SetBaseMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/grass.bmp"), 0));//0.40 - 0.75spTerrainTexture->SetDetailMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/stone.bmp"), 0));//0.05 - 0.40spTerrainTexture->SetGlowMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/dirt.bmp"), 0));//0.0 - 0.05spMesh->AttachProperty(spTerrainTexture);// Set the shader on the modelNiMaterialPtr spTerrainMaterial = NiSingleShaderMaterial::Create("Terrain");spMesh->ApplyAndSetActiveMaterial(spTerrainMaterial);m_spAnimationTime = NiNew NiFloatExtraData(0.0f);spMesh->AddExtraData("AnimationTime", m_spAnimationTime);}void ObjectShader::UpdateTerrain(NiPoint3 cameraPosition, float DT){m_spAnimationTime->SetValue(m_spAnimationTime->GetValue() + (DT * 30));//Updates the Shader to allow Wave motionNiShaderFactory::UpdateGlobalShaderConstant("EyePos", sizeof(cameraPosition), &cameraPosition);//Updates the Camera Position for Lighting.}I have a theory that if I calculated the distance of each vertex from the center of the sphere, then I could possibly figure out how high each point is from the center. This allowing me work out what texture to texture it. But I've no idea how to approach this idea in a shader as I've no real grasp on shaders yet. Especially with doing something like this.Thanks to anyone who can help me out with this. It's driving me insane. I need to complete this section before I can move on to the next part of my project.Thanks,Scott.   ;  In the vertex shader, you get the vertex position in object space. Assuming you created your sphere centered at the origin, it's trivial to calculate the "height" of the vertex: just calculate the length of the vertex position vector.You can then store this height value in a TEXCOORD, say TEXCOORD1. The GPU will then automagically interpolate the height value for you, and you will have access to the specific height of the fragment in the fragment shader.   ;  Thanks a heap for that. This is how I thought It might be done but I'm unsure on if I need any special function calls in the shader. As I'm not sure how I can call getLength on a vertex insider a shader. Thanks so much for you're help though :)   ;Quote:Original post by ScottehyThanks a heap for that. This is how I thought It might be done but I'm unsure on if I need any special function calls in the shader. As I'm not sure how I can call getLength on a vertex insider a shader. Thanks so much for you're help though :)length = sqrt(x*x + y*y + z*z);Theres probably some function (magnitude) that does this for you in HLSL but its been a long time since I've used HLSL so I can't recall what it is.   ;  I know that the function is distance(,) and it takes in 2 vectors. The maths isn't my issue. But it just crashes and dies when I change anything. I tried to change my structure to:struct VS_OUTPUT{    float4 Pos : POSITION;    float4 Normal   : NORMAL;    float4 Color    : COLOR;    float2 TexCoord : TEXCOORD;    float4 VecEye   : TEXCOORD1;    float  dist: TEXCOORD2;};So i could store it in a TEXCOORD like lingfors said but no luck. As soon as I'm editing anything in there it just crashes.   ;  There is a method length to calculate a vector's length.http://msdn.microsoft.com/en-us/library/bb509617(VS.85).aspx   ;Quote:Original post by Scottehy    float2 TexCoord : TEXCOORD;should probably be    float2 TexCoord : TEXCOORD0;;  Yup, i realize that and found that function. But wouldn't I have to store my value inside the structure? Yet as soon as I'm adding something else to it. It basically just screws up. Or am I able to change it and store it else where?   ;  I store my actual texture coord in there though. So changing that wont help me. Don't I need to add another one like float dist : TEXCOORD0 - Or something like that to store the length of the vector?   