Jump to content
  • Advertisement
Sign in to follow this  
anders211

Meshes rendered with the aid of shaders corrupted in windows 64 bit

This topic is 789 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi

I have 2 computers at home. So far for about 5 years I have worked on my stationary PC with Windows XP 32 bit. I have shader files and some meshes in my game and they are rendered OK on my Win XP 32 bit machine. I am using here Visual Studio 2005.

Today I installed Windows7 64 bit on my second computer - notebook. It has integrated graphic card but it supports pixel 1.1/vertex shader 2.0 which I used in my code when compiling shaders. I installed Visual Studio 2013, then move my source files to notebook, configure settings for DirectX 9.0 June SDK (add d3d9.lib, d3dx9.lib). I still use x86 not x64 lib because compiler doesn't see directx9 functions. My source files are compilable.

 

The problem is that each mesh which is rendered in my game with effect file/shader (not fixed function pipeline) is corrupted. Here example of football gate where net mesh is corrupted:

[attachment=31243:problemWithShaders.png]

The similar artefact is with my animation character.

Meshes rendered with the aid of fixed function pipeline are OK (like posts, crossbar, ball on above figure).

Any hint what might be wrong?

Edited by anders211

Share this post


Link to post
Share on other sites
Advertisement

Hi.

Do you need to recompile the shaders for a 64 bit, or the mesh file needs to be saved as a 64 bit file.

Share this post


Link to post
Share on other sites

OK thanks, I will check if issue is resolved when adding flag D3DXSHADER_USE_LEGACY_D3DX9_31_DL because on Win7 x64 default shader compiler is DIRECTX 10 HLSL. I I couldn't check that because shader is not compiling with this flag.

Edited by anders211

Share this post


Link to post
Share on other sites

I used DirectX SDK PIX in order to debug shader and there is none any strange error apart from "unredundant SetRenderStates or sthm like that".

Here is my code:

RetCode Effect::createEffect(const char* fileName,DWORD flag)
{
ID3DXBuffer* errBuff = NULL;


//flag 0, D3DXSHADER_DEBUG, D3DXSHADER_SKIPVALIDATION, D3DXSHADER_SKIPOPTIMIZATION, D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, D3DXSHADER_USE_LEGACY_D3DX9_31_DLL
//effect - pointer to the ID3DXEffect interface
HRESULT hr = D3DXCreateEffectFromFile(pDev,fileName,NULL,NULL,flag,NULL,&effect,&errBuff);
                                //no preprocessor definitions //no ID3DXIncluse interface //do not share parameters


// output any error messages
if(errBuff)
{
    ::MessageBox(NULL, (char*)errBuff->GetBufferPointer(), "Error", MB_OK);
    errBuff->Release();
    errBuff = NULL;
}


if(FAILED(hr))
{
    d3d::CheckError(hr, "Effect::D3DXCreateEffectFromFile()");
    return NOK;
}


return OK;
}

I used flags:

D3DXSHADER_DEBUG|D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3DXSHADER_SKIPOPTIMIZATION

Moreover I think on win32 xp I used also directX 10 HLSL compiler (despite I didn't have installed directX10) as it is written in documentation:

Beginning with the December 2006 SDK, the DirectX 10 HLSL compiler is now the default compiler in both DirectX 9 and DirectX 10. See Effect-Compiler Tool for details.

 

 

Part of my effect file (the body implementation should be OK):

//Vertex Shader input
struct VS_INPUT
{
    float3 position    : POSITION; //bind space
    float3 normal      : NORMAL;
    float2 coord       : TEXCOORD;
};


//Vertex Shader outputs
struct VS_OUTPUT_MEDIUM
{
    vector position  : POSITION;
    vector diffuse   : COLOR;
    float2 coord     : TEXCOORD;
};


//Pixel Shader inputs
struct PS_INPUT_MEDIUM
{
    vector diffuse : COLOR;
    float2 coord   : TEXCOORD;
};
technique Medium
{
    pass P0
    {
        vertexShader = compile vs_2_0 BlendMediumVS();
        pixelShader  = compile ps_2_0 BlendMediumPS();
    }
}
Edited by anders211

Share this post


Link to post
Share on other sites

I have already solved the problem. The solution is to use software vertex processing instead of hardware vertex processing when creating d3d device at the beginning of program initialization. I don't know why it helps, because for my notebook GetDeviceCaps functions return D3DDEVCAPS_HWTRANSFORMANDLIGHT what means device supports transformation and lighting in hardware. If anyone has idea it is the right solution and hardware vertex processing really shouldn't work on my notebook please comment. Graphic card is Intel GMA 4500 (notebook Dell Latitude E5400). This makes also a little problem because what condition should now I used in order to choose for user vertex/hardware processing as we see " if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)" is not good choice.

 
 //Get device capabilities
   D3DCAPS9 caps; 
   i32 vp = 0;
   pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
   if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
      vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;//I removed this one D3DCREATE_HARDWARE_VERTEXPROCESSING; and helped it solved problem for my notebook
   else
   {
  MessageBox(hWnd,"Attention: Software vertex processing will be used","Game",MB_OK|MB_ICONWARNING);
  vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
   }
...
...
   retVal = pD3D->CreateDevice(AdapterToUse, DeviceType, hWnd, vp, &d3dpp, &pDev);
Edited by anders211

Share this post


Link to post
Share on other sites


You're probably doing something undefined that just happened to work on a different setup. Mismatched vertex layouts, or who knows what.

 

That switching from hardware to software processing of anything fixed your issue means this is probably true.  You did something that was wrong and shouldn't have worked, but it did by coincidence on the specific setup you were using at the time, and it gave you the impression that you didn't have any bugs.  But you probably did.

 


//Vertex Shader outputs
struct VS_OUTPUT_MEDIUM
{
    vector position  : POSITION;
    vector diffuse   : COLOR;
    float2 coord     : TEXCOORD;
};


//Pixel Shader inputs
struct PS_INPUT_MEDIUM
{
    vector diffuse : COLOR;
    float2 coord   : TEXCOORD;
};

 

Was this snippet copy/pasted from your actual shader file, or did you just provide a recreation?  I have a feeling that this isn't actually any part of your shader code, but I could be wrong.  Regardless, it'd probably be useful to see your engine code for setting up to use that shader; maybe you have a format mismatch that your previous setup was incorrectly lenient on.

Share this post


Link to post
Share on other sites

OK, I am pasting as much code as possible, but not too much in order to put focus only on the code regarded the problem:

//prepare effect file responsible for rendering net:
//do once at setup scene
D3DXMatrixPerspectiveFovLH(&d3d::MatProj, D3DXToRadian(45), 1.6f, 0.1f, 1000);
filename = "shaders\\ePosNorTexIndex.fx";
if(eEffects[id]->createEffect((char *)filename.c_str(),D3DXSHADER_DEBUG|D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3DXSHADER_SKIPOPTIMIZATION) == NOK) 
return NOK;
eEffects[posNorTexIndex]->setParameterByName("mtrl", p_Mtrl);
eEffects[posNorTexIndex]->setParameterByName("lightStr", p_LightStr);
eEffects[posNorTexIndex]->setParameterByName("MatWorld", p_MatWorld);
eEffects[posNorTexIndex]->setParameterByName("MatWorldInvTrans", p_MatWorldInvTrans);
eEffects[posNorTexIndex]->setParameterByName("MatWVP", p_MatWVP);
eEffects[posNorTexIndex]->setParameterByName("textura", p_Textura); //texture
eEffects[posNorTexIndex]->setTechniqueByName("Medium", p_Medium); //texture
eEffects[posNorTexIndex]->setTechniqueByName("High", p_High); //texture
eEffects[posNorTexIndex]->setTechnique(p_Medium); //set by default Medium details
eEffects[posNorTexIndex]->setParameterByName("toCam", p_toCam);
eEffects[posNorTexIndex]->setParameterByName("MatWorldBone", p_MatWorldBone);
eEffects[posNorTexIndex]->setParameterByName("delta", p_Delta);
...
Effect::getEffects(Effect::posNorTexIndex)->setValue(Effect::p_LightStr, (void *) &lightSource, sizeof(LightStr)); 
...
... 
//do each frame at the beginning of render:
...
MatView = cam->GetCamView();
D3DXMATRIX MatViewProj = MatView * d3d::MatProj;
D3DXMatrixIdentity(&MatWorld);  // my MatWorld is unit matrix
D3DXMATRIX MatWorldInv, MatWorldInvTrans;
D3DXMatrixInverse(&MatWorldInv, 0, &MatWorld);
D3DXMatrixTranspose(&MatWorldInvTrans, &MatWorldInv);
D3DXMATRIX MatWVP = MatWorld*MatViewProj;
...
Effect::getEffects(Effect::posNorTexIndex)->setMatrix(Effect::p_MatWorld, &MatWorld);
Effect::getEffects(Effect::posNorTexIndex)->setMatrix(Effect::p_MatWorldInvTrans, &MatWorldInvTrans);
Effect::getEffects(Effect::posNorTexIndex)->setMatrix(Effect::p_MatWVP, &MatWVP);
Effect::getEffects(Effect::posNorTexIndex)->setFloatArray(Effect::p_toCam, (float *)cam->GetCamPos(), 3);
...
//draw net which is movable object
Effect* effect = Effect::getEffects(Effect::posNorTexIndex);
effect->activateTechnique();
effect->begin();
effect->setFVF();
effect->setMatrix(Effect::p_MatWorldBone, &mMatOrientation);
effect->setFloatArray(Effect::p_Delta, &mDelta[0].x, 3*MAX_NET_VERTICES); //set table to 0 for debugging purposes,MAX_NET_VERTICES = 120
for(u32 i=0; i<mNet.subsets; ++i) 
{
   //Set material
   Mtrl mtrl = Mtrl(mNet.mat.at(i).Ambient, mNet.mat.at(i).Diffuse, mNet.mat.at(i).Specular, mNet.mat.at(i).Power);
   effect->setValue(Effect::p_Mtrl, (void *) &mtrl, sizeof(Mtrl));
   //Set textures
   effect->setTexture(Effect::p_Textura, mNet.texture.at(i));
   //Draw mesh subset
   for(u32 j=0; j<effect->getNumPasses(); ++j)
   {
       effect->beginPass(j);
       if(mNet.mesh != NULL)
           mNet.mesh->DrawSubset(i); //this one is invoked
       else
           mNet.pmesh->DrawSubset(i);
   effect->endPass();
   }

}
effect->end();
...

Most of method from Effect class:

ID3DXEffect* effect; //I have this one in my Effect class
...
void Effect::setTechniqueByName(const char *tech, effectTech id)
{
    if(id < p_TechMax)
        techniques[id] = effect->GetTechniqueByName(tech);
    else
    {
        ::MessageBox(NULL,"Error in Effect::setTechniqueByName()", "Error", MB_OK|MB_ICONWARNING);
         return;
     }
}
void Effect::setTechnique(effectTech id)
{
    if(id < p_TechMax)
        if(techniques[id] != NULL)
        {
            technique = techniques[id];
            return;
        }
     ::MessageBox(NULL,"Error in Effect::setTechnique() - new technique not set", "Error", MB_OK|MB_ICONWARNING);
}
void Effect::setFloat(effectPar id, float &x)
{
    effect->SetFloat(parameter[id], x);
}
void Effect::setBool(effectPar id, bool &x)
{
    effect->SetBool(parameter[id], x);
}
void Effect::setInt(effectPar id, i32 &x)
{
    effect->SetInt(parameter[id], x);
}
void Effect::setVector(effectPar id, D3DXVECTOR4* x)
{
    effect->SetVector(parameter[id], x);
}
void Effect::setMatrix(effectPar id, D3DXMATRIX* x)
{
    effect->SetMatrix(parameter[id], x);
}
void Effect::setFloatArray(effectPar id, float* x, u32 size)
{
effect->SetFloatArray(parameter[id], x, size);
}
void Effect::setBoolArray(effectPar id, i32* x, u32 size)
{
effect->SetBoolArray(parameter[id], x, size);
}
void Effect::setIntArray(effectPar id, i32* x, u32 size)
{
effect->SetIntArray(parameter[id], x, size);
}
void Effect::setVectorArray(effectPar id, D3DXVECTOR4* x, u32 size)
{
effect->SetVectorArray(parameter[id], x, size);
}
void Effect::setMatrixArray(effectPar id, D3DXMATRIX* x, u32 size)
{
effect->SetMatrixArray(parameter[id], x, size);
}
void Effect::setValue(effectPar id, void* x, u32 size)
{ 
    effect->SetValue(parameter[id], x, size);
}
void Effect::setTexture(effectPar id, IDirect3DTexture9 *texture)
{
effect->SetTexture(parameter[id], texture);
}
void Effect::getTechniqueByName(const char *technique)
{
this->technique = effect->GetTechniqueByName(technique);
}
RetCode Effect::validateTechnique()
{
   HRESULT hr;
   if(technique != NULL)
       hr = effect->ValidateTechnique(technique);
   else 
       return NOK;

   if(FAILED(hr))
      return NOK;
   return OK;
}
void Effect::activateTechnique()
{
effect->SetTechnique(technique);
}
u32* Effect::begin(DWORD flag)
{
    //Flag - 0, D3DXFX_DONOTSAVESTATE, D3DXFX_DONOTSAVESHADERSTATE
    effect->Begin(&numPasses, flag);
    return &this->numPasses;
}
void Effect::end()
{
    effect->End();
}
void Effect::beginPass(u32 i)
{
    if(i < numPasses)
      effect->BeginPass(i);
    else
      ::MessageBox(NULL, "Effect():beginPass() - number of passes exceeded!", "Error", MB_OK);
}
void Effect::endPass()
{
    effect->EndPass();
}


u32 Effect::getNumPasses() const
{
    return numPasses;
}
D3DXHANDLE Effect::getParameter(effectPar id)
{
    if(id < p_Max)
        if(parameter[id] != NULL)
            return parameter[id];
    ::MessageBox(NULL,"Error in Effect::getParameter()", "Error", MB_OK|MB_ICONWARNING);
    return NULL;
}
void Effect::setParameterByName(const char *param, effectPar id)
{
    if(id < p_Max)
        parameter[id] = effect->GetParameterByName(0, param);
    else
    {
        ::MessageBox(NULL,"Error in Effect::setParameterByName()", "Error", MB_OK|MB_ICONWARNING);
         return;
     }
}
D3DXHANDLE Effect::getTechnique(effectTech id)
{
    if(id < p_TechMax)
        if(techniques[id] != NULL)
            return techniques[id];

    ::MessageBox(NULL,"Error in Effect::getTechnique()", "Error", MB_OK|MB_ICONWARNING);
    return NULL;
}
void Effect::setFVF() 
{
    if(pVDecl != NULL)
        pDev->SetVertexDeclaration(pVDecl); //it is d3d::declPosNorTexBlend1
}
//it is defined as below:
const D3DVERTEXELEMENT9 declPosNorTexBlend1[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{0, 32, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0},
D3DDECL_END()
};
 
 
 
ePosNorTexIndex.fx content:
(delta table is for making net moving when for example ball hits it. For debugging purposes I init this table to 0.120 is the number of vertices in mesh. Each mesh has in vertex buffer "index". For debugging purposes I also tested net mesh without this index in vertex buffer with effect file without delta variable. The results were the same, so this might be excluded from causing the bug.
I used Mediium technique.
uniform extern float4x4 MatWorld;
uniform extern float4x4 MatWorldInvTrans;
uniform extern float4x4 MatWVP;
uniform extern float3 toCam;
uniform extern float4x4 MatWorldBone;
uniform extern float3 delta[120];


struct Mtrl
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float  Power;
};
struct LightStr
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Direction;  //direction into the source light
};


uniform extern Mtrl     mtrl;
uniform extern LightStr lightStr;


uniform extern texture textura;
sampler Sampl = sampler_state
{
Texture = <textura>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU  = WRAP;
    AddressV  = WRAP;
};


//Vertex Shader input
struct VS_INPUT
{
    float3 position    : POSITION; //bind space
    float3 normal      : NORMAL;
    float2 coord       : TEXCOORD;
    int    index       : BLENDINDICES;
};


//Vertex Shader outputs
struct VS_OUTPUT_MEDIUM
{
    float4 position  : POSITION;
    float4 diffuse   : COLOR;
    float2 coord     : TEXCOORD;
};
struct VS_OUTPUT_HIGH
{
    float4 position  : POSITION;
    float3 normal    : TEXCOORD0;
    float3 toCam     : TEXCOORD1;
    float2 coord     : TEXCOORD2;
};


//Pixel Shader inputs
struct PS_INPUT_MEDIUM
{
    float4 diffuse : COLOR;
    float2 coord   : TEXCOORD;
};
struct PS_INPUT_HIGH
{
    float3 normal    : TEXCOORD0;
    float3 toCam  : TEXCOORD1;
    float2 coord     : TEXCOORD2;
};


//Shaders for MEDIUM level of details
VS_OUTPUT_MEDIUM BlendMediumVS(VS_INPUT input)
{
VS_OUTPUT_MEDIUM output = (VS_OUTPUT_MEDIUM)0;

//output position
float4 pos = mul(float4(input.position, 1.0f), MatWorldBone);
pos.x += delta[input.index].x;
pos.y += delta[input.index].y;
pos.z += delta[input.index].z;


// Transform to homogeneous clip space.
output.position = mul(pos, MatWVP);


//Output diffuse
    float4 normal = mul(float4(input.normal, 0.0f), MatWorldBone);
    normal.w = 0.0f;


    // Transform to World space
    normal = mul(normal, MatWorldInvTrans);  
    normal = normalize(normal);


    // Light calculation
    float4 LightDirection = float4(lightStr.Direction, 0.0f);
    float s = dot(LightDirection, normal);
    if(s < 0.0f) s = 1.0f; //cosinus <-1,1>


    output.diffuse = (mtrl.Ambient * lightStr.Ambient) +
                     (s * (lightStr.Diffuse * mtrl.Diffuse)); //alpha from ambient is taken 


    // Forward texture coordinate
    output.coord = input.coord;


    return output;
}


vector BlendMediumPS(PS_INPUT_MEDIUM input) : COLOR
{
// sample appropriate textures
vector texColor = tex2D(Sampl, input.coord);


// combine texel colors
vector pixelColor = input.diffuse * texColor;


return pixelColor;
}


//Shaders for HIGH level of details
VS_OUTPUT_HIGH BlendHighVS(VS_INPUT input)
{
VS_OUTPUT_HIGH output = (VS_OUTPUT_HIGH)0;
    
    //output position
    float4 pos = mul(float4(input.position, 1.0f), MatWorldBone);
pos.x += delta[input.index].x;
pos.y += delta[input.index].y;
pos.z += delta[input.index].z;


// Transform to homogeneous clip space.
output.position = mul(pos, MatWVP);


//Output diffuse
    float4 normal = mul(float4(input.normal, 0.0f), MatWorldBone);
    normal.w = 0.0f;


// Transform normal to world space.
output.normal = mul(normal, MatWorldInvTrans).xyz;


// Transform vertex position to world space.
float3 posVert  = mul(pos, MatWorld).xyz;
// Compute the vector from the vertex to the camera.
output.toCam = toCam - posVert;


// Forward texture coordinate
    output.coord = input.coord;


return output;
}


vector BlendHighPS(PS_INPUT_HIGH input) : COLOR
{
// Interpolated normals can become unnormal--so normalize.
input.normal = normalize(input.normal);
input.toCam  = normalize(input.toCam);


// Compute the reflection vector.
float3 r = reflect(lightStr.Direction, input.normal);


// Determine how much (if any) specular light makes it into the eye.
float t  = pow(max(dot(r, input.toCam), 0.0f), mtrl.Power);


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


// Compute the ambient, diffuse and specular terms separatly. 
float3 specular = t*(mtrl.Specular*lightStr.Specular).rgb;
float3 diffuse = s*(mtrl.Diffuse*lightStr.Diffuse).rgb;
float3 ambient = (mtrl.Ambient*lightStr.Ambient).rgb;


// sample appropriate textures
vector texColor = tex2D(Sampl, input.coord);


// Combine the color from lighting with the texture color.
float3 color = (ambient + diffuse)*texColor.rgb + specular;


// Sum all the terms together and copy over the diffuse alpha.
    return float4(color, mtrl.Diffuse.a*texColor.a); //alpha from texture and diffuse material
}


technique Medium
{
    pass P0
    {
vertexShader = compile vs_2_0 BlendMediumVS();
        pixelShader  = compile ps_2_0 BlendMediumPS();


CullMode = None;
        AlphaRef = 1;
        AlphaFunc = GreaterEqual;
        AlphaTestEnable = true;


AlphaBlendEnable = true;
SrcBlend = SrcAlpha;
DestBlend = InvSrcAlpha;
BlendOp = Add;


ColorOp[0] = SelectArg1;
        ColorArg1[0] = Texture;
        AlphaOp[0] = SelectArg1;
AlphaArg1[0] = Texture;


AlphaOp[1] = Disable;
        ColorOp[1] = Disable;
    }
}


technique High
{
    pass P0
    {
vertexShader = compile vs_2_0 BlendHighVS();
        pixelShader  = compile ps_2_0 BlendHighPS();


CullMode = None;
        AlphaRef = 1;
        AlphaFunc = GreaterEqual;
        AlphaTestEnable = true;


AlphaBlendEnable = true;
SrcBlend = SrcAlpha;
DestBlend = InvSrcAlpha;
BlendOp = Add;


ColorOp[0] = SelectArg1;
        ColorArg1[0] = Texture;
        AlphaOp[0] = SelectArg1;
AlphaArg1[0] = Texture;


AlphaOp[1] = Disable;
        ColorOp[1] = Disable;
    }
}
Edited by anders211

Share this post


Link to post
Share on other sites

I thought the problem is with Intel GMA graphic card that software vertex processing has to be used but I have the same issue with my PC where Nvidia GT440 graphic card is installed. Here for sure hardware vertex processing can be used. I narrowed down the issue. The issue occurs only when I do:

1. Load mesh from x file

2. do:

void* dataVB = NULL;
if(FAILED(pVB->Lock(0, 0, &dataVB, D3DLOCK_DISCARD))) 
    throw runtime_error("Goalnet::addToNetMeshVertexIndices::Lock");

/*float* data = (float *) dataVB;
for(u32 i=0; i<mNet.mesh->GetNumVertices(); ++i)
{       
   u32 x = i;
   memcpy(&data[9*i+8], &x, 4);
   mVertexPos[i] = D3DXVECTOR3(data[9*i],data[9*i+1],data[9*i+2]);
}*/

if(FAILED(pVB->Unlock()))
   throw runtime_error("Goalnet::addToNetMeshVertexIndices::Unlock");

3. Render with my effect file/shaders

 

When step 2 is skipped my graphic is rendered as in windows 32bit. So it seems like invoking vertex buffer lock and vertex buffer unlock triggers issue. Issue isn't triggered by memcpy because I put it in comments and the problem still occurs. So it is lock/unlock. Anyone knows how to solve the issue? Maybe graphic card returns from its RAM to PC RAM values in 32 bits when doing Lock but when doing unlock it gets values as 64 bits and this makes graphic distorted? Exceptions aren\t invoked.

Edited by anders211

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!