• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Migi0027

DX11
DX11 - HLSL - Parallax Mapping

13 posts in this topic

Now I've been trying to implement parallax mapping for a short while now, and I'm not quite sure if the result is right. The result (look at the plane):

 

1q04cp.png

 

Now there I have shown you the result of Diffuse, Parallax, Parallax with Normal Mapping rendering, and a blank space of course!

 

Now to some code:

 

(Relevant) Vertex Shader:

 

float binormal = cross(tangent,normal);

float3x3 tbnmatrix = transpose(float3x3(tangent,binormal,normal));
output.toeyetangent = mul((eyepos - output.position),tbnmatrix);

 

 

(Relevant) Pixel Shader:

 

float height = parallaxmap.Sample(ss, texCoord);

float3 toeyetangent = normalize(input.toeyetangent);
float2 offset = toeyetangent.xy*height*0.04f;

texCoord += offset;

 

 

And If you wan't, the full shader:

 

cbuffer ConstantObjectBuffer : register (b0)
{
	matrix worldMatrix; 
	matrix viewMatrix; 
	matrix projectionMatrix; 

	float4x4 rotation;
	float4 ambientcol;
	float texture_repeat;
	float3 tr_sace;
	float4 clipColor;
	float3 _instancePos;
	float inSPACE;
};

cbuffer ConstantFrameBuffer : register (b1)
{
	float4 lightvec;
	float4 lightcol;
	float time;
	float _wireframe;
	float2 wffspace;

	matrix tmat;
	matrix svp;
};

cbuffer UberData : register (b2)
{
	float _diffuse;
	float _texture;
	float _opacityEnable;
	float _directionall;
	float _bumpmap;
	float _fog;
	float _wind;
	float _pixelDisorter;
	float _disorterAmount;
	float _specular;
	float _doClip;
	float _terrain;
	float _instance;
	float _selected;
	float _windspeed;
	float _windamount;
	float _particle;
	float _shadows;
	float _envreflect;
	float _invDoClip;
	float _parallaxMapping;
	float3 ssspace;
};

cbuffer ConstantMatrixBuffer : register (b3)
{
	float4x4 world;
	float4x4 view;
	float4x4 projection;
	float4 eyepos;
	float3 cforward;
	float _space;
};

cbuffer ConstantFogBuffer : register (b4)
{
	float FogStart;
	float FogEnd;
	float2 __space;
	float3 FogColor;
	float __space2;
};

cbuffer ConstantSpecularBuffer : register (b5)
{
	float specularPower;
	float3 ____space;
    float4 specularColor;
};

cbuffer ConstantTerrainBuffer : register (b6)
{
	float t_nchannels;
	float3 t_space;
	float4 slopeActivation;
};

cbuffer ConstantParticleBuffer : register (b7)
{
	float particle_pastTime;
	float particle_lifeTime;
	float particle_fallOff;
	float _cpbspace;
};

cbuffer ShadowBuffer : register (b8)
{
	matrix sWorld;
	matrix lightViewMatrix;
	matrix lightProjectionMatrix;
	float3 sLightPos;
}

// Meshes
Texture2D txt : register(t0); // base
Texture2D txt2 : register(t1); // bump
Texture2D parallaxmap : register(t12); // parallax
Texture2D txt3 : register(t2); // opacity
TextureCube env : register (t11);

//Terrain
Texture2D terrChannel1 : register(t3);
Texture2D terrChannel2 : register(t4);
Texture2D terrChannel3 : register(t5);
Texture2D terrChannel4 : register(t6);

Texture2D gBuffer_Normals : register(t7);
Texture2D gBuffer_Position : register(t8);
Texture2D gBuffer_Random : register(t9);
Texture2D gBuffer_Shadows : register(t10);

sampler shadowss = 
sampler_state
{
    Texture = <gBuffer_Shadows>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

SamplerState ss;

sampler NormalMapSampler = sampler_state
{
   Texture = <txt2>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = Clamp;
   AddressV  = Clamp;
};

struct VOut
{
    float4 worldPos : POSITION; 
	float3 normal : NORMAL; 
	float3 Specnormal : NORMAL2; 
    float2 texcoord : TEXCOORD; 
	float4 tangent : TANGENT; 
    float4 position : SV_POSITION;
    float3 WorldNormal : TEXCOORD2;
	float Depth : FOG;
    float4 color : COLOR;
    float3 View : VIEWD;
	float4 lightViewPosition : TEXCOORD5;
	float3 L : TEXCOORD6;
	float3 N : TEXCOORD7;
	float3 lightPos : TEXCOORD8;
	float3 toeyetangent : EYET;
};

VOut VShader(float4 position : POSITION, float4 normal : NORMAL, float2 texcoord : TEXCOORD, float4 tangent : TANGENT, float3 instancePosition : INSTANCEPOS)
{
    VOut output;

	if (_wind == 1)
	{
		position.x += sin(time+position.x*10);
		position.y += cos(time+position.y*10);
		position.z += sin(time+position.y*10);

		// Parameters controlling the wind effect.
		float3 WindDirection = float3(1, 0, 0);
		float WindWaveSize = 0.1;
		float WindRandomness = 1;
		float WindSpeed = _windspeed;
		float WindAmount = _windamount;

		// Work out how this vertex should be affected by the wind effect.
		float waveOffset = dot(position, WindDirection) * WindWaveSize;
    
		waveOffset += 2 * WindRandomness;
    
		// Wind makes things wave back and forth in a sine wave pattern.
		float wind = sin(time * WindSpeed + waveOffset) * WindAmount;
    
		// But it should only affect the top two vertices of the billboard!
		wind *= (1 - texcoord.y);
    
		position += float4(WindDirection * wind, position.w);
	}

	if (_instance == 1)
	{
		position.x += instancePosition.x;
		position.y += instancePosition.y;
		position.z += instancePosition.z;
	}

	position.w = 1.0f;

	// Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);

    output.worldPos = mul(position, worldMatrix);
	output.WorldNormal = normalize(mul(normal, worldMatrix));

	output.color = float4(0,0,0,1);

    // set the ambient light
	if (_diffuse == 1)
	{
		output.color += ambientcol;
	}

	if (_texture == 1)
	{
		output.texcoord = texcoord;
	}

	// Stuff for dir and bump
	if (_directionall == 1)
	{
		float4 norm = normalize(mul(rotation, normal));
		float diffusebrightness = saturate(dot(norm, lightvec));
		output.color += lightcol * diffusebrightness;
	}

	if (_bumpmap == 1)
	{
		output.normal = normal;
		output.tangent = tangent;
	}

	float3 Cnormal = normalize(mul(normal, worldMatrix));
	output.Specnormal = Cnormal;
	output.View = normalize(eyepos - output.worldPos);

	// SHADOW
    
	if (_shadows == 1)
	{
		// Calculate the position of the vertice as viewed by the light source.
		output.lightViewPosition = mul(position, worldMatrix);
		output.lightViewPosition = mul(output.lightViewPosition, lightViewMatrix);
		output.lightViewPosition = mul(output.lightViewPosition, lightProjectionMatrix);
    
		// Calculate the normal vector against the world matrix only.
		output.normal = mul(normal, (float3x3)worldMatrix);
	
		// Normalize the normal vector.
		output.normal = normalize(output.normal);

		// Calculate the position of the vertex in the world.
		float4 worldPosition = mul(position, worldMatrix);

		// Determine the light position based on the position of the light and the position of the vertex in the world.
		output.lightPos = sLightPos - worldPosition.xyz;

		// Normalize the light position vector.
		output.lightPos = normalize(output.lightPos);
	}
	// END

	if (_parallaxMapping == 1)
	{
		float binormal = cross(tangent,normal);

		float3x3 tbnmatrix = transpose(float3x3(tangent,binormal,normal));
		output.toeyetangent = mul((eyepos - output.position),tbnmatrix);
	}

	// Final stuff
	output.Depth = output.position.z;
	output.color.a = 1;

    return output;
}

// SSAO Operations
float3 getPosition(in float2 uv)
{
	return gBuffer_Position.Sample(ss, uv).xyz;
}

float3 getNormal(in float2 uv)
{
	return normalize(gBuffer_Normals.Sample(ss, uv).xyz * 2.0f - 1.0f);
}

float2 getRandom(in float2 uv)
{
	return normalize(gBuffer_Random.Sample(ss, float2(800,600) * uv / float2(64,64)).xy * 2.0f - 1.0f);
}

float doAmbientOcclusion(in float2 tcoord,in float2 uv, in float3 p, in float3 cnorm)
{
	float3 diff = getPosition(tcoord + uv) - p;
	const float3 v = normalize(diff);
	const float d = length(diff)*2; //scale
	return max(0.0,dot(cnorm,v)-5)*(1.0/(1.0+d))*1; // Intensity
}

float4 PShader(VOut input) : SV_TARGET
{
	// If it's wireframe, skip everything else
	if (_wireframe == 1)
	{
		return float4(1,1,1,1); // we may have to do something with this, not sure yet...
	}

	float4 color = input.color;

	float4 spec = float4(0,0,0, 1);
	float4 tex = float4(0,0,0, 1);
	float4 bump = float4(0,0,0, 1);

	input.texcoord.xy *= texture_repeat;
	float2 texCoord = input.texcoord;

	if (_texture == 1)
	{
		if (_parallaxMapping == 1)
		{
			float height = parallaxmap.Sample(ss, texCoord);

			float3 toeyetangent = normalize(input.toeyetangent);
			float2 offset = toeyetangent.xy*height*0.04f;

			texCoord += offset;
		}

		if (_pixelDisorter == 1)
		{
			// Distortion factor
			float NoiseX = _disorterAmount * (time/1000) * sin(input.texcoord.x * input.texcoord.y+time/1000);
			NoiseX=fmod(NoiseX,8) * fmod(NoiseX,4); 

			// Use our distortion factor to compute how much it will affect each
			// texture coordinate
			float DistortX = fmod(NoiseX,5);
			float DistortY = fmod(NoiseX,5+0.002);
 
			// Create our new texture coordinate based on our distortion factor
			texCoord = float2(DistortX,DistortY);
		}

		if (!_bumpmap)
		{
			float4 txtColor = txt.Sample(ss, texCoord);
			color *= txtColor;
		}
		else if (_bumpmap == 1)
		{
			float4 Color = txt.Sample(ss, texCoord);
			float3 N = (2.0 * (txt2.Sample(ss, texCoord))) - 1.0;
			// diffuse
			float D = saturate(dot(N, lightvec));
			// reflection
		    float3 R = normalize(2 * D * N - lightvec);
			// specular
			float S = pow(saturate(dot(R, texCoord*input.tangent)), 2);
			const float4 Ambient = float4(0.3, 0.3, 0.3, 1.0);

			color *= Color*Ambient + Color * D + Color*S; 
		}

		if (_doClip == 1)
		{
			if (_invDoClip == 1)
			{
				color.a = 1.0f - saturate(txt.Sample(ss, texCoord));
			}
			else 
			{
				color.a = saturate(txt.Sample(ss, texCoord));
			}
		}
	}

	if (_specular == 1)
	{
		float4 normal = float4(input.Specnormal, 1.0);
		float4 diffuse = saturate(dot(-lightvec,normal));
		float4 reflect = normalize(2*diffuse*normal-lightvec);
		float4 specular = pow(saturate(dot(reflect,input.View)),15);
 
		color += float4(1,1,1,1)*specular;
	}

	if (_opacityEnable == 1)
	{
		float4 opacity = saturate(txt3.Sample(ss, texCoord));

		color.a *= opacity;
	}

	if (_terrain == 1)
	{
		float4 grassColor;
		float4 slopeColor;
		float4 rockColor;
		float slope;
		float blendAmount;
		float4 textureColor;

		grassColor = terrChannel1.Sample(ss, input.texcoord);

		slopeColor = terrChannel2.Sample(ss, input.texcoord);

		rockColor  = terrChannel3.Sample(ss, input.texcoord);

		// Calculate the slope of this point.
		slope = 1.0f - input.normal.y;

		// Determine which texture to use based on height.
		if(slope < 0.2)
		{
			blendAmount = slope / 0.2;
			textureColor = lerp(grassColor, slopeColor, blendAmount);
		}
	
		if((slope < 0.7) && (slope >= 0.2))
		{
			blendAmount = (slope - 0.2) * (1.0f / (0.7 - 0.2));
			textureColor = lerp(slopeColor, rockColor, blendAmount);
		}

		if(slope >= 0.7) 
		{
			textureColor = rockColor;
		}

		color *= textureColor;
	}

	if (_particle == 1)
	{
		float range = particle_lifeTime-particle_fallOff;

		if (particle_pastTime > range)
		{
			color.a *= saturate(1.0f - (1.0f/( (particle_lifeTime-(particle_lifeTime - particle_fallOff)) / (particle_pastTime-(particle_lifeTime - particle_fallOff)) )));
			
			color.a -= 1.0f/(distance(eyepos.xyz, input.Depth)) / 50.0f;
		}
	}

	if (_shadows == 1)
	{
		float bias;
		float2 projectTexCoord;
		float depthValue;
		float lightDepthValue;
		float lightIntensity;
		float4 textureColor;

		// Set the bias value for fixing the floating point precision issues.
		bias = 0.0001f;

		// Calculate the projected texture coordinates.
		projectTexCoord.x =  input.lightViewPosition.x / input.lightViewPosition.w / 2.0f + 0.5f;
		projectTexCoord.y = -input.lightViewPosition.y / input.lightViewPosition.w / 2.0f + 0.5f;

		// Determine if the projected coordinates are in the 0 to 1 range.  If so then this pixel is in the view of the light.
		if((saturate(projectTexCoord.x) == projectTexCoord.x) && (saturate(projectTexCoord.y) == projectTexCoord.y))
		{
			// Sample the shadow map depth value from the depth texture using the sampler at the projected texture coordinate location.
			depthValue = gBuffer_Shadows.Sample(ss, projectTexCoord).r;

			// Calculate the depth of the light.
			lightDepthValue = input.lightViewPosition.z / input.lightViewPosition.w;

			// Subtract the bias from the lightDepthValue.
			lightDepthValue = lightDepthValue - bias;

			// Compare the depth of the shadow map value and the depth of the light to determine whether to shadow or to light this pixel.
			// If the light is in front of the object then light the pixel, if not then shadow this pixel since an object (occluder) is casting a shadow on it.
			if(lightDepthValue < depthValue)
			{
				// Calculate the amount of light on this pixel.
				lightIntensity = saturate(dot(input.normal, -lightvec));

				if(lightIntensity > 0.0f)
				{
					// Determine the final diffuse color based on the diffuse color and the amount of light intensity.
					color += (ambientcol * lightIntensity) * color.a;

					// Saturate the final light color.
					color = saturate(color);
				}
			}
			else
			    color.rgb *= 0.3f;
		}
	}

	if (_fog == 1)
	{
		float l = saturate((input.Depth - FogStart) / (FogEnd - FogStart));
		color = float4(lerp(color,FogColor, l), color.a);
	}

	if (_selected == 1)
	{
		color += float4(0, 0, 0.2, 0);
	}

	color.a = saturate(color.a);

    return color;
}

 

 

Thanks! biggrin.png

0

Share this post


Link to post
Share on other sites

Can anybody tell me if the parallax mapping is right? huh.png

 

I'm not asking for a fix, I'm just asking for a check, and if you have the time and you want to, you can give me an advice if you want to. happy.png

0

Share this post


Link to post
Share on other sites

Looks like a bug I had a long while ago when first playing around with parallax mapping. The blurry strifes aren't supposed to be there, really. Just run the DX9 sdk-parallax mapping sample, and compare yours to this. I can't tell you what the exact problem was for me back then and how I solved it, but just study the directx sdk examples (there is actually also one for DX11, I believe)...

0

Share this post


Link to post
Share on other sites

Pic, please confirm:

 

Nope, still wrong. Unless you want a nightmarish game where everything is blurred and shapes are washed up, thats far, far from looking as it should. Its probably just a small space-convertion issue of some kind. Here is how it is supposed to look like.

 

 

 

 

 

0

Share this post


Link to post
Share on other sites

It looks definately better than on the sphere, but still, compared to this (see attachment) it looks washed up. Would need to see it in motion to see it more clearl, though.

0

Share this post


Link to post
Share on other sites

Are you sure that this isn't how it's supposed to look?

Are you asking a question, or telling us that your implementation is correct?  It isn't clear to me (or anyone else I think) what your motive is for writing this thread.  If there is something about your results that seem wrong to you, then please ask about it.  If this is a thread for you to demonstrate your implementation, then put that in the description.

 

So far, I haven't seen you really ask any substantive questions - please help us to understand what you want.

1

Share this post


Link to post
Share on other sites

Are you asking a question, or telling us that your implementation is correct?

 

Then what about this? huh.png

 

No, thats still not a valid question :S

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • By lonewolff
      Hi Guys,
      I am revisiting an old DX11 framework I was creating a while back and am scratching my head with a small issue.
      I am trying to set the pixel shader resources and am getting the following error on every loop.
      As you can see in the below code, I am clearing out the shader resources as per the documentation. (Even going overboard and doing it both sides of the main PSSet call). But I just can't get rid of the error. Which results in the render target not being drawn.
      ID3D11ShaderResourceView* srv = { 0 }; d3dContext->PSSetShaderResources(0, 1, &srv); for (std::vector<RenderTarget>::iterator it = rtVector.begin(); it != rtVector.end(); ++it) { if (it->szName == name) { //std::cout << it->srv <<"\r\n"; d3dContext->PSSetShaderResources(0, 1, &it->srv); break; } } d3dContext->PSSetShaderResources(0, 1, &srv);  
      I am storing the RT's in a vector and setting them by name. I have tested the it->srv and am retrieving a valid pointer.
      At this stage I am out of ideas.
      Any help would be greatly appreciated
       
    • By bowerbirdcn
      hi, guys, how to understand the math used in CDXUTDirectionWidget ::UpdateLightDir 
      the  following code snippet is taken from MS DXTU source code
       
        D3DXMATRIX mInvView;
          D3DXMatrixInverse( &mInvView, NULL, &m_mView );
          mInvView._41 = mInvView._42 = mInvView._43 = 0;
          D3DXMATRIX mLastRotInv;
          D3DXMatrixInverse( &mLastRotInv, NULL, &m_mRotSnapshot );
          D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix();
          m_mRotSnapshot = mRot;
          // Accumulate the delta of the arcball's rotation in view space.
          // Note that per-frame delta rotations could be problematic over long periods of time.
          m_mRot *= m_mView * mLastRotInv * mRot * mInvView;
          // Since we're accumulating delta rotations, we need to orthonormalize 
          // the matrix to prevent eventual matrix skew
          D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mRot._11;
          D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mRot._21;
          D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mRot._31;
          D3DXVec3Normalize( pXBasis, pXBasis );
          D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
          D3DXVec3Normalize( pYBasis, pYBasis );
          D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
       
       
      https://github.com/Microsoft/DXUT/blob/master/Optional/DXUTcamera.cpp
    • By YixunLiu
      Hi,
      I have a surface mesh and I want to use a cone to cut a hole on the surface mesh.
      Anybody know a fast method to calculate the intersected boundary of these two geometries?
       
      Thanks.
       
      YL
       
    • By hiya83
      Hi, I tried searching for this but either I failed or couldn't find anything. I know there's D11/D12 interop and there are extensions for GL/D11 (though not very efficient). I was wondering if there's any Vulkan/D11 or Vulkan/D12 interop?
      Thanks!
    • By lonewolff
      Hi Guys,
      I am just wondering if it is possible to acquire the address of the backbuffer if an API (based on DX11) only exposes the 'device' and 'context' pointers?
      Any advice would be greatly appreciated
  • Popular Now