Jump to content

  • Log In with Google      Sign In   
  • Create Account


Necrolis

Member Since 12 May 2010
Offline Last Active Sep 17 2014 03:19 AM

Topics I've Started

Emulating SetGammaRamp in a shader

20 March 2014 - 02:06 PM

I've been trying to figure out a way to map a gamma ramp generation function I have (obtained through RE) to an HLSL/GLSL function/operator, in an effort to emulate the "look and feel" of an older game I fiddle with in my spare time. 

 

however, I'm failing to get anywhere because I'm not sure how the gamma ramp set by D3DDevice9::SetGammaRamp gets used when outputting a pixel. what I'm looking for is: if I have the RGB tuple "x" what operations are performed on x's channels using the ramp that yield the final pixel rendered to the back buffer?

 

The ramp generation looks like so if it helps in any way:

void GenGammaRamp(long dwGamma, double fContrast, double* pRamp)
{
    double fGamma = (double)dwGamma;
    double fFractGamma = 0.01 * fGamma;
    double fGammaPercent = 100.0 / fGamma;
    double fRampEnd = 255.0;
    double fMaxGamma = 65535.0;
    double fGammaFactor = 1.0 / fRampEnd;
    for(double fRamp = 0.0; fRamp < fRampEnd; fRamp += 1.0)
    {
        double fGammaStep = fGammaFactor * fRamp * fMaxGamma * fFractGamma;
        fGammaStep = fGammaStep > fMaxGamma ? fMaxGamma : fGammaStep;
        double fFinalGamma = (pow(fGammaFactor * fRamp,fGammaPercent) * fMaxGamma * (100.0 - fContrast) + fGammaStep * fContrast) * 0.01;

        pRamp[(int)fRamp] = fFinalGamma;
    }
}

(the values get converted to back to 8/16/32 bit integers just before the are sent off to the driver).


Optimizing Ray-Sphere Intersections

13 September 2013 - 10:09 AM

I've made a few ray tracers in the past, but they where normally focussed on small aspects, taking shortcuts for many things, however recently I needed to make one for a uni project and decided to go all out. So after setting up my math libs, getting all the ground work into place (which most importantly includes a 4DOF FPS camera) it came time to trace a few spheres to test both the ray casting and get ready to implement a BVH/BSP scheme.

 

First thing I tried was this snippet of code (take from this wonderful set of articles):

Vector dst = vCenter - r.GetOrigin();
float b = dst.dot(r.GetDirection());
float c = b * b - dst.dot(dst) + fRadiusSquared;

if(c < 0)
	return INTERSECT_NONE;

float d = std::sqrtf(c), r1 = b - d, r2 = b + d;
if(r2 < 0)
	return INTERSECT_NONE;

if(r1 < 0)
{
	fDistance = r2;
	return INTERSECT_INSIDE;
}

fDistance = r1;
return INTERSECT_OUTSIDE;

it works, but far off objects come out very "fuzzy" and jagged, clearing up as you get closer:

nhMz8D0.png

 

After trying quite a few variants (such as this) which all suffered the same problem, I suspected a problem in my maths code; however, using the following code (adapted from here, based on an unoptimized quadratic formula, massively slows down rendering):

	//Compute A, B and C coefficients
	Vector o = r.GetOrigin() - vCenter;
	float c = o.length_squared_fast() - fRadiusSquared;
	if(c < 0)
		return INTERSECT_INSIDE;

	float a = r.GetDirection().dot(r.GetDirection());
	float b = 2 * r.GetDirection().dot(o);

	//Find discriminant
	float disc = b * b - 4 * a * c;
    
	// if discriminant is negative there are no real roots, so return 
	// false as ray misses sphere
	if (disc < 0)
		return INTERSECT_NONE;

	// compute q as described above
	float disc_sqrt = sqrtf(disc);
	float q = (b < 0) ? (-b - disc_sqrt) / 2.0f : (-b + disc_sqrt) / 2.0f;

	// compute t0 and t1
	float t0 = q / a;
	float t1 = c / q;

	// make sure t0 is smaller than t1
	if (t0 > t1)
		std::swap(t0,t1);

	// if t1 is less than zero, the object is in the ray's negative direction
	// and consequently the ray misses the sphere
	if (t1 < 0)
		return INTERSECT_NONE;

	// if t0 is less than zero, the intersection point is at t1
	if (t0 < 0)
	{
		fDistance = t1;
		return INTERSECT_OUTSIDE;
	}
	// else the intersection point is at t0
	else
	{
		fDistance = t0;
		return INTERSECT_OUTSIDE;
	}

it comes out correctly: HfTyOif.png

 

and for the life of me a can't figure out why the optimized variants seem to degrade so badly...

Anybody got any hints/advice as to whats going wrong here? is this just a side-effect from approximating it geometrically?


[DX11] Sprite/Text Rendering

01 February 2011 - 10:16 AM

So I decided recently to update to directx 11, and first thing on my list to get going where SDF based fonts, however I couldn't find a thing on 2d drawing in Dx11, other than MJP's code in his Depth Sprites example and in Hieroglyph3. I didn't understand it much but thought if I could get it running in my code and play with it I would be able to understand it (I have read the description of his shader in another post, so I get what the maths is doing, plus I saw the new (-1,1) (1,-1) scheme that I was unaware of in previous attempts). this is the code I'm using (Z-buffering is disabled):
class FontManager
	{
		private:
			ID3D11SamplerState* pSamplerState;
			ID3D11VertexShader* pVertexShader;
			ID3D11PixelShader* pPixelShader;
			ID3D11InputLayout* pLayout;
			ID3D11Buffer* pConstantBuffer;
			ID3D11Buffer* pVertexBuffer;
			ID3D11Buffer* pInstanceBuffer;
			ID3D11Buffer* pIndexBuffer;

			struct FontVertex
			{
				D3DXVECTOR2 pPosition;
				D3DXVECTOR2 pTexture;
			};

			struct GlyphInstance
			{
				D3DXMATRIX pTransform;
				D3DXVECTOR4 pColor;
				struct DrawRect
				{
					float fXpos;
					float fYpos;
					float fWidth;
					float fHeight;
				}pDrawRect;
			};

		public:
			FontManager(ID3D11Device* pDevice)
			{
				Create(pDevice);
			}

			~FontManager()
			{
				Destroy();
			}

			BOOL Create(ID3D11Device* pDevice)
			{
				ID3D10Blob* pErrorMessage;
				ID3D10Blob* pVertexShaderBuffer;
				ID3D10Blob* pPixelShaderBuffer;
				D3D11_BUFFER_DESC pConstantBufferDesc;
				D3D11_SAMPLER_DESC pSamplerDesc;

				if(FAILED(D3DX11CompileFromFile(L"Shaders\\Text.hlsl",NULL,NULL,"SpriteVS","vs_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL,&pVertexShaderBuffer,&pErrorMessage,NULL)))
				{
					if(pErrorMessage)
						ShaderError(pErrorMessage,NULL,L"Shaders\\Text.hlsl");
					else
						MessageBox(NULL,L"Shaders\\Text.hlsl",L"Missing Shader File",MB_OK);
					
					return FALSE;
				}

				if(FAILED(D3DX11CompileFromFile(L"Shaders\\Text.hlsl",NULL,NULL,"SpritePS","ps_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL,&pPixelShaderBuffer,&pErrorMessage,NULL)))
				{
					if(pErrorMessage)
						ShaderError(pErrorMessage,NULL,L"Shaders\\Text.hlsl");
					else
						MessageBox(NULL,L"Shaders\\Text.hlsl",L"Missing Shader File",MB_OK);

					return false;
				}

				if(FAILED(pDevice->CreateVertexShader(pVertexShaderBuffer->GetBufferPointer(),pVertexShaderBuffer->GetBufferSize(),NULL,&pVertexShader)))
					return FALSE;

				if(FAILED(pDevice->CreatePixelShader(pPixelShaderBuffer->GetBufferPointer(),pPixelShaderBuffer->GetBufferSize(),NULL,&pPixelShader)))
					return FALSE;

				D3D11_INPUT_ELEMENT_DESC pFontLayout[] =
				{
					{ "POSITION",	0, DXGI_FORMAT_R32G32_FLOAT,		0,	0,								D3D11_INPUT_PER_VERTEX_DATA,	0 },
					{ "TEXCOORD",	0, DXGI_FORMAT_R32G32_FLOAT,		0,	D3D11_APPEND_ALIGNED_ELEMENT,	D3D11_INPUT_PER_VERTEX_DATA,	0 },
					{ "TRANSFORM",	0, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	0,								D3D11_INPUT_PER_INSTANCE_DATA,	1 },
					{ "TRANSFORM",	1, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	16,								D3D11_INPUT_PER_INSTANCE_DATA,	1 },
					{ "TRANSFORM",	2, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	32,								D3D11_INPUT_PER_INSTANCE_DATA,	1 },
					{ "TRANSFORM",	3, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	48,								D3D11_INPUT_PER_INSTANCE_DATA,	1 },
					{ "COLOR",		0, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	64,								D3D11_INPUT_PER_INSTANCE_DATA,	1 },
					{ "SOURCERECT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT,	1,	80,								D3D11_INPUT_PER_INSTANCE_DATA,	1 }
				};

				unsigned int nElements = ARRAY(pFontLayout);
				if(FAILED(pDevice->CreateInputLayout(pFontLayout,nElements,pVertexShaderBuffer->GetBufferPointer(),pVertexShaderBuffer->GetBufferSize(),&pLayout)))
					return FALSE;

				pVertexShaderBuffer->Release();
				pPixelShaderBuffer->Release();

				FontVertex pFontQuad[] =
				{
					{D3DXVECTOR2(0.0f, 0.0f),D3DXVECTOR2(0.0f, 0.0f)},
					{D3DXVECTOR2(1.0f, 0.0f),D3DXVECTOR2(1.0f, 0.0f)},
					{D3DXVECTOR2(1.0f, 1.0f),D3DXVECTOR2(1.0f, 1.0f)},
					{D3DXVECTOR2(0.0f, 1.0f),D3DXVECTOR2(0.0f, 1.0f)}
				};

				D3D11_BUFFER_DESC pVertexBufferDesc, pInstanceBufferDesc, pIndexBufferDesc;
				D3D11_SUBRESOURCE_DATA pVertexData, pIndexData;

				pVertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
				pVertexBufferDesc.ByteWidth = sizeof(FontVertex) * 4;
				pVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
				pVertexBufferDesc.CPUAccessFlags = 0;
				pVertexBufferDesc.MiscFlags = 0;
				pVertexBufferDesc.StructureByteStride = 0;
				pVertexData.pSysMem = pFontQuad;
				pVertexData.SysMemPitch = 0;
				pVertexData.SysMemSlicePitch = 0;
				if(FAILED(pDevice->CreateBuffer(&pVertexBufferDesc,&pVertexData,&pVertexBuffer)))
					return FALSE;

				pInstanceBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
				pInstanceBufferDesc.ByteWidth = sizeof(GlyphInstance) * 1024;
				pInstanceBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
				pInstanceBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
				pInstanceBufferDesc.MiscFlags = 0;
				pInstanceBufferDesc.StructureByteStride = 0;
				if(FAILED(pDevice->CreateBuffer(&pInstanceBufferDesc,NULL,&pInstanceBuffer)))
					return FALSE;

				UINT pFontQuadLayout[] = {0, 1, 2, 3, 0, 2};
				pIndexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
				pIndexBufferDesc.ByteWidth = sizeof(UINT) * 6;
				pIndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
				pIndexBufferDesc.CPUAccessFlags = 0;
				pIndexBufferDesc.MiscFlags = 0;
				pIndexBufferDesc.StructureByteStride = 0;
				pIndexData.pSysMem = pFontQuadLayout;
				pIndexData.SysMemPitch = 0;
				pIndexData.SysMemSlicePitch = 0;
				if(FAILED(pDevice->CreateBuffer(&pIndexBufferDesc,&pIndexData,&pIndexBuffer)))
					return FALSE;

				pConstantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
				pConstantBufferDesc.ByteWidth = sizeof(D3DXVECTOR4);
				pConstantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
				pConstantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
				pConstantBufferDesc.MiscFlags = 0;
				pConstantBufferDesc.StructureByteStride = 0;
				if(FAILED(pDevice->CreateBuffer(&pConstantBufferDesc,NULL,&pConstantBuffer)))
					return FALSE;

				pSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
				pSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
				pSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
				pSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
				pSamplerDesc.MipLODBias = 0.0f;
				pSamplerDesc.MaxAnisotropy = 1;
				pSamplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
				pSamplerDesc.BorderColor[0] = 0;
				pSamplerDesc.BorderColor[1] = 0;
				pSamplerDesc.BorderColor[2] = 0;
				pSamplerDesc.BorderColor[3] = 0;
				pSamplerDesc.MinLOD = 0;
				pSamplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
				if(FAILED(pDevice->CreateSamplerState(&pSamplerDesc,&pSamplerState)))
					return FALSE;

				return TRUE;
			}

			void Destroy()
			{
				pSamplerState->Release();
				pVertexShader->Release();
				pPixelShader->Release();
				pLayout->Release();
				pConstantBuffer->Release();
				pVertexBuffer->Release();
				pInstanceBuffer->Release();
				pIndexBuffer->Release();
			}

			void Render(ID3D11DeviceContext* pDeviceContext, ID3D11ShaderResourceView* pTexture, const wchar_t* wszString)
			{
				D3DXMATRIX pTransform;
				D3DXMatrixIdentity(&pTransform);
				GlyphInstance pInstance = {pTransform,D3DXVECTOR4(1.0f,1.0f,1.0f,1.0f),{10,10,256,256}};
				D3D11_MAPPED_SUBRESOURCE pMap;
				if(FAILED(pDeviceContext->Map(pInstanceBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&pMap)))
					return;
				
				*(GlyphInstance*)pMap.pData = pInstance;
				pDeviceContext->Unmap(pInstanceBuffer,0);
				pDeviceContext->IASetInputLayout(pLayout);
				pDeviceContext->VSSetShader(pVertexShader,NULL,0);
				pDeviceContext->PSSetShader(pPixelShader,NULL,0);
				pDeviceContext->PSSetSamplers(0,1,&pSamplerState);
				unsigned int dwStride[] = {sizeof(FontVertex),sizeof(GlyphInstance)}; 
				unsigned int dwOffset[] = {0,0};
				ID3D11Buffer* pBuffers[] = {pVertexBuffer,pInstanceBuffer};
				pDeviceContext->IASetVertexBuffers(0,2,pBuffers,dwStride,dwOffset);
				pDeviceContext->IASetIndexBuffer(pIndexBuffer,DXGI_FORMAT_R32_UINT,0);
				pDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
				D3D11_MAPPED_SUBRESOURCE pMappedResource;
				if(FAILED(pDeviceContext->Map(pConstantBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&pMappedResource)))
					return;

				D3DXVECTOR4* pData = reinterpret_cast<D3DXVECTOR4*>(pMappedResource.pData);
				*pData = D3DXVECTOR4(256,256,1024,768);//hc'ed for now: texture is 256x256, viewport is 1024x768
				pDeviceContext->Unmap(pConstantBuffer,0);
				pDeviceContext->VSSetConstantBuffers(0,1,&pConstantBuffer);
				pDeviceContext->PSSetShaderResources(0,1,&pTexture);
				pDeviceContext->DrawIndexedInstanced(6,1,0,0,0);
			}
    };
Can anyone (MJP?) exlpain to me what I'm missing, as this draws nothing :(...

EDIT: just to make it clear, this is about my third attempt at creating a ortho projecting VS, best I got was building a ortho transform matrix and mul'ing by that, but that cause quite a few other problems. The code about attempts to rending out the entire font texture to screen as one giant quad at (10,10), just a a test. It might also help to note that this code doesn't crash, nor does it stall the pipeline, its just not rendering anything, at least in the viewport...

[DX9] Deferred Message Processing

10 December 2010 - 02:15 AM

I like to fiddle around a lot with multi-threading my 'engine', however, I've been running into a few problems, mainly due to this article on MSDN. but I really don't want to merge my message pump and rendering loop, but at the same time, I really want to avoid problems and the D3D multithreaded flag... However thanks to work, I no longer have any time to test anything, so instead, its time for pseudo-code :)

So, how well would a setup like this work in place of the standard message pump:


while(not shutdown)
{
if(PeekAndGetMessge(Msg))
QueueThreadTask(new InputJob(Msg)) //queue the message in the thread pool, do it at the highest level possible
//the render thread has its own computations to do

if(not CheckCoop()) //yay now its being called from the message thread
RecoverDevices()

DoRendering() //this is too, but its not being delayed by input processing
}



or does D3D require that the messages go through the WNDPROC before I queue them? what at the downfalls of something like this? or is there a better way? With this kinda of model, can I also queue off resource creation(V/I buffers, textures, shaders etc)?

Something I'm curious about is if I need a WNDPROC even if I don't dispatch messages to it via DispatchMessage.

[DX9/PS 1.4] Clipping Text/Sprites

18 October 2010 - 09:48 PM

Is it possible to clip text using a pixel shader, allowing one to not have to break batches to call ScissorRect?

My problem is how to pass the clipping rect and then process it. (I seem to have problems swizzling under HLSL with ps 1.4 and problems using "if"'s).

I would assume that to clip it, I would just call clip(-1)? or can this be optimized to some thing better like clip(Out.Pos.x - rect.x)?

I'm using an FVF of (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) for the text at the moment if that helps any, but I'm trying to move away from using the FFP.

PARTNERS