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.
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.
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.
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 example
Terrain NSF
Terrain HLSL
Snipet Of the Shader in cpp
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.
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 example
Terrain 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_Point3 EyePos Artist 0.0 } Global_Attributes { Attrib_Point3 EyePos Artist 0.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_Global EyePos 5 3 } 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 HLSL
sampler2D 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 cpp
void ObjectShader::CreateTerrain(NiMeshPtr spMesh){ // dirt, stone, grass, snow NiTexturingPropertyPtr spTerrainTexture = NiNew NiTexturingProperty("Data/dirt.bmp"); //--------------------------------------Terrain Shaders In Use----------------------------------------------- spTerrainTexture->SetNormalMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/dirt.bmp"), 0));//0.75 - 1.00 spTerrainTexture->SetBaseMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/grass.bmp"), 0));//0.40 - 0.75 spTerrainTexture->SetDetailMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/stone.bmp"), 0));//0.05 - 0.40 spTerrainTexture->SetGlowMap(NiNew NiTexturingProperty::Map(NiSourceTexture::Create("Data/dirt.bmp"), 0));//0.0 - 0.05 spMesh->AttachProperty(spTerrainTexture); // Set the shader on the model NiMaterialPtr 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 motion NiShaderFactory::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.
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 Scottehy
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 :)
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:
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.
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
http://msdn.microsoft.com/en-us/library/bb509617(VS.85).aspx
Quote:Original post by Scottehyfloat2 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?
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement