[solved] whats wrong with this quad?

Started by
9 comments, last by Norman Barrows 7 years, 2 months ago

i'm getting shaders working in caveman 3.0

i just got the effect file from basicHLSL working in a test routine in the game, using SetVertexDeclartation SetStream SetIndices, Effect->SetTexture, and DrawInxededPrimitive, instead of mesh->DrawSubset.

the game only uses d3dxmeshes for loading. it only stores the vb's, ib's, numverts, num_prinitieves, and .x filename.

so far i've done tests that draw tiny.x with her texturemap, and tiny.x with textures from the game.

but when i tried to draw a a quad mesh from the game, the texture is messed up. like clamp is on or something. the quad is a unit quad centered on the origin lying in the x,z plane. it was made in blender as i recall, and exported as .x

to make sure , i did a dump of the vb and ib:

vert x y z u v

0 -0.5 0 .5 1 1

1 .5 0 .5 0 1

2 .5 -0 -.5 0 0

3 -.5 -0 -.5 1 0

note that all those .5's area actually .4999987's

index vertex#

0 0

1 1

2 2

3 0

4 2

5 3

looking down from above with pos z towards the top, both the quad verts and the verts for both tris are listed in clockwise order. the 1st tri is the upper right half of the quad, and the second is the lower left half.

but the u,v coords mirror the texture across the line x=z.

to determine what was wrong, i created a second qaud with code, and it works:

= vb1[0].position.x 0.0f
= vb1[0].position.y 1.0f
= vb1[0].position.z 0.0f
= vb1[1].position.x 1.0f
= vb1[1].position.y 1.0f
= vb1[1].position.z 0.0f
= vb1[2].position.x 1.0f
= vb1[2].position.y 0.0f
= vb1[2].position.z 0.0f
= vb1[3].position.x 0.0f
= vb1[3].position.y 0.0f
= vb1[3].position.z 0.0f
= vb1[0].tu 0.0f
= vb1[0].tv 0.0f
= vb1[1].tu 1.0f
= vb1[1].tv 0.0f
= vb1[2].tu 1.0f
= vb1[2].tv 1.0f
= vb1[3].tu 0.0f
= vb1[3].tv 1.0f
= ib1[0] 0
= ib1[1] 1
= ib1[2] 2
= ib1[3] 0
= ib1[4] 2
= ib1[5] 3
cr result Zd3d_device_ptr->CreateVertexBuffer (UINT)(sizeof(Zvertexrec)*4) D3DUSAGE_WRITEONLY ZFVF D3DPOOL_MANAGED &m1.vb NULL
cr result Zd3d_device_ptr->CreateIndexBuffer (UINT)(sizeof(short)*6) D3DUSAGE_WRITEONLY D3DFMT_INDEX16 D3DPOOL_MANAGED &m1.ib NULL
c m1.vb->Lock 0 0 &p 0
c memcpy p vb1 sizeof(Zvertexrec)*4
c m1.vb->Unlock
c m1.ib->Lock 0 0 &p 0
memcpy( p, ib1, sizeof(unsigned short)*6 );
c m1.ib->Unlock
the effect file is basicHLSL.fx, with the vertex transform based on sin(time) stripped out, and just the 1 light technique.
i've tried both linear and aniso for min and mag filters
i thought textureTrasnformFlags might be the cause, but it doesn't seem to be supported.
the test is triggered from playtest menu #3, off of the main playtest menu in the game, which is accessed while in FPS mode, via alt-F12.
so the pipeline is in whatever state it was when it finished the call to draw_outdoors(); the game keeps the pipeline in a default state of alpha test and blend and snow blending off, and aniso and mipmaps on.
so it seems there is something wrong with that quad. the UVs most likely. i need to test other meshes from the game as well. i did try one other mesh rock.x, but seemed to get the same results. the texture used for the tests is a 256x256 grass tile.
i'm concerned that maybe blender is spiiting out UVs that the shader doesn't like for some reason.
the sampler code is
sampler MeshTextureSampler =
sampler_state
{
Texture = <g_MeshTexture>;
MipFilter = LINEAR;
MinFilter = ANISOTROPIC;
MagFilter = ANISOTROPIC;
// TextureTransformFlags = DISABLE;
};
PS_OUTPUT RenderScenePS( VS_OUTPUT In)
{
PS_OUTPUT Output;
Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV); // * In.Diffuse; // Lookup mesh texture and modulate it with diffuse
return Output;
}
EDIT:
it definitely seems to be the UVs.
i changed the quad made with code to a unit quad in the x,z plane centered at the origin. that worked. then i changed the UV's to mirror across x=z, the way the quad from the game does, and i get the banding and streaking - ie it doesn't work. guess i'll try a fresh quad from blender next...
EDIT 2:
just tried a fresh quad from blender and it doesn't work.
blender version: 2.78a - should be the newest. it was installed on the new PC perhaps a month ago.
3d view - object mode - add - mesh - plane.
2nd window - UV editor - image - open image - grass_tile1.bmp
1st window - switch to edit mode - mesh - uv unwrap - unwrap
file - save as - plane2.blend
file - export - directx - plane2.x - LH ccords, up axis = y, export selected (the plane), export: meshes, normals, and uv's.
change the game to load plane2.x instead of plane.x.
plane.x is the original one that doesn't work.
a dump of plane2.x reveals:
-1 0 -1 .0001 .9999
1 0 -1 .9999 .9999
1 0 1 .9999 .0001
-1 0 1 .0001 .0001
3,2,1
3,1,0
again, the tris are listed CW, not CCW.
but the texture is not mirrored across x=z. UL of quad is UL of tex, and so on.
and it doesn't work.
i'm slowly rotating the quad around global x, and neither side works. neither front nor back facing.
is it the CW listing of verts?
guess i'll try swizzling the indices....

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Advertisement

It's probably the CW listing of vertices. I'm guessing you don't have back face culling on, which would give a mirrored appearance when viewed from the back.

It's probably the CW listing of vertices. I'm guessing you don't have back face culling on, which would give a mirrored appearance when viewed from the back.

i changed the ib for plane2.x to

3,1,2

3,0,1

IE ccw order. no effect.

does fixed function backface culling even have an effect on shaders?

the quad that does work - the one created with code - shows backface. so you see the grass texture on both sides of the quad.

by process of elimination, it would seem that it must the the UVs, not the indices. CW winding vs backface culling is a separate kettle of fish to fry.

i'm hoping its something related to blender export, and something I can fixup once at load time, then save the changes.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

i took the quad that works and shifted it down and left to the origin.

only the part in the first quadrant textured correctly. the rest seemed to be clamped.

so i added a call to turn off clamp in the fixed function pipeline at the beginning of the shader test and now it works with every mesh in the game, except the original plane.x, and the plane2.x that i made in blender.

my guess is the last thing it was drawing before the test was an alpha tested plant (IE savanna grass), and that's why clamp was on in the fixed function pipeline. grass also turns cull off - and cull is off when the test runs.

i don't specify any address mode in the sampler.

so there seems to be an issue with fixed function clamp mode, and an issue with the UV mapping or exporting of a plane from blender.

i'm pretty sure that by dragging around the corners of the selection box in the UV editor you can get the plane's UV's correct. maybe play with the handedness and up axis on export too.

it appears that mixing shaders and fixed function in dx9, shaders are just another "switch/dial" you can set on the pipeline, that override some but not necessarily all "switches/dials" that are considered "fixed function". this is going to be interesting..... (and probably not in a good way).

so if you don't specify an address mode in a sampler, whatever address mode the fixed function pipeline was in is the address mode you get?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Not entirely sure what the effects are of setting states in both the fixed function and programmable pipeline. This link seems to suggest that some states are shared and others are not.

This link seems to suggest that some states are shared and others are not.

Bookmark that! Nice link! Thanks!

EDIT: just discovered that's a new topic not included in the june 2010 sdk docs.

yes, it seems there is only one pipeline in dx9, and some stages of the pipeline are fixed, and some can be fixed or programmable (IE vertex and pxiel shader stages).

one cool thing is it seems i can use fixed function to turn alpha testing on/off, with no change to the shader! guess i'd better double check that list though.... <g>

i tried moving the quad around. it only textured correctly when it was in the first quadrant.

i tried changing the UVs in blender - no effect.

i tried changing the UVs in code - no effect - ok this is getting seriously weird!

so i decided to compare what i had (based on basicHLSL example) to the crate demo from Luna's DX9 shader book (yes - i broke down and bought a copy and DL'd the sample code).

the only difference was i was using CreateTexrtureFormFileEx, and he was using CreateTexrtureFormFile.

so this works:

D3DXCreateTextureFromFile(Zd3d_device_ptr, "crate.jpg", &mCrateTex);
and this doesn't:
D3DXCreateTextureFromFileExA(Zd3d_device_ptr, "crate.jpg",
D3DX_DEFAULT,D3DX_DEFAULT, // width,height
0, // mip lvls. 0 or default = full chain, 1= no mip maps.
0, // usage: not dynamic, not render tgt.
D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,
D3DX_FILTER_NONE, // image filter
D3DX_FILTER_POINT, // mip filter. none=vanishing mipmaps problem. point=wrap problems.
// linear,tri,and box blend the keycolor into the edges of the image (dark edges problem).
// no mips causes sparkle problem.
0xFF000000, // 0XFF000000, color key
NULL,NULL,&mCrateTex);
as you can see from my comments when i first started working on alpha tested plants, point filtering of mipmaps has issues.
shader_test_3 currently draws the first face of luna's cube: a quad from -1,-1 to 1 1 in x and y, at z=-1.
with createTextureFormFile, it works.
with Ex, you get 4 copies of the image, one in each quadrant. as though texture scaling and wrap were on. these are the wrap issues mentioned in my comments.
Guess i'll try no filtering for mipmaps or no mipmaps.
The issue is with dx9 auto generation of mip levels. it blends the background into the edges of the image. and there does not seem to be a way to prevent it, except to make your own and not sample background pixels.
3D graphics programming reminds me a lot of telecom programming. Imagine the pipeline (or the modem) is a big control panel with about 50 switches, dials, and buttons on it. and all 50 have to set correctly at the same time for it to work at all. but when you find and flip that 50th switch... Boom! all of a sudden it works.
Time to try flipping a few more switches, like switching D3DX_FILTER_POINT to D3DX_FILTER_NONE.
That is unless somebody has an answer to this: filter modes and auto-mipmap generation vs the tex2D() lookup function - which seems to be the issue.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Well, its not CreateTextureFromFile.

I tried it again, to make sure, and now it doesn't work.

A quad from <0,0 to 1,1> works. i get 1 crate.

If i move the quad to <-.5,0 to 1,1>, i get 1 crate to the right of the y-z plane, and half a crate to the left.

it must be something in sampler stage state...

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Does your shader input match the stream? Maybe your shader expects normal data or something.

Does your shader input match the stream? Maybe your shader expects normal data or something.

vertex shader inputs:

//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
float3 vNormal : NORMAL,
float2 vTexCoord0 : TEXCOORD0,
uniform int nNumLights)
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;
Output.Position = mul(vPos, g_mWorldViewProjection); // Transform the position from object space to homogeneous projection space
vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // Transform the normal from object space to world space // normal (world space)
float3 vTotalLightDiffuse = float3(0,0,0); // Compute simple directional lighting equation
for(int i=0; i<nNumLights; i++ )
vTotalLightDiffuse += g_LightDiffuse * max(0,dot(vNormalWorldSpace, g_LightDir));
Output.Diffuse.rgb = g_MaterialDiffuseColor * vTotalLightDiffuse + g_MaterialAmbientColor * g_LightAmbient;
Output.Diffuse.a = 1.0f;
Output.TextureUV = vTexCoord0; // Just copy the texture coordinate through
return Output;
}
vertex format declaration:
D3DVERTEXELEMENT9 vertex_format[] =
{
' stream 0, offset 0, float3, no tesselation, position, usage index 0
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
' stream 0, offset 0, float3, no tesselation, normal, usage index 0
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
' stream 0, offset 0, float2, no tesselation, tex coords, usage index 0
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
the corresponding FVF for fixed function:
// const DWORD ZFVF=(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0) );
and the code to set the format:
' ---------------------------------------- create and set vertex declaration ----------------------------------------------------------
cr result Zd3d_device_ptr->CreateVertexDeclaration vertex_format &vertex_declaration
!= result D3D_OK
c msg3 "create vertex declaration error"
ret
.
c Zd3d_device_ptr->SetVertexDeclaration vertex_declaration
tried swizzling normal and texture positions in the VB, no apparent effect. OTOH, almost all values are -1, 0 , or 1.
I'm still guessing its a texture sampler stage setting that's not correct. I'm about to go over that list of switches now...

so far i have:

//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler MeshTextureSampler =
sampler_state
{
Texture = <g_MeshTexture>;
MinFilter = Anisotropic;
MagFilter = LINEAR;
MipFilter = LINEAR;
MaxAnisotropy = 8;
// MipFilter = LINEAR; // NONE | LINEAR
// MinFilter = LINEAR; // LINEAR | ANISOTROPIC
// MagFilter = LINEAR; // LINEAR | ANISOTROPIC
AddressU = WRAP;
AddressV = WRAP;
};

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

think i found it...

from the june 2010 dx9 docs:

D3DVERTEXELEMENT9 Structure

Defines the vertex data layout. Each vertex can contain one or more data types, and each data type is described by a vertex element.

Syntax

typedef struct D3DVERTEXELEMENT9 {
WORD Stream;
WORD Offset;
BYTE Type;
BYTE Method;
BYTE Usage;
BYTE UsageIndex;
} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9;

Offset WORD Offset from the beginning of the vertex data to the data associated with the particular data type.

so the offset of normal is 12 bytes from the start of the vertex struct (3 float position * 4 bytes per float = 12 bytes), and the offset of texture is 24 bytes from the start of the vertex struct.

in my vertex declaration all offsets are zero. i was thinking of them as stream offsets, not element offsets.

so it was using position for both position and normal, and using position.x and position.y for u and v.

time to fix that.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement