Sign in to follow this  
vagos21

managed d3d (vb.net) simple diffuse shader looks like toon shading?

Recommended Posts

vagos21    122
Hello everyone,

i'm using vb.net and managed d3d to make a converter of some game 3d files to the known obj file format. i used to make maxscript but decided to change to a standalone app.

importing data from the binary files was pretty easy, i've dealt with d3d before, and so was rendering stuff on screen. but then i wanted to use environment reflections, normal and specular maps, so i turned to shaders.

i have to admit, making a shader work for the first time was a pain, but finally i got it right. i'm passing all the parameters and matrices needed to the shader, and the result shows up. that's when the problem kicks in! the shader i have in the screenshots is a simple gray diffuse shader, and it comes up like toon shading, where black areas are in the shadow from the light, and white are lit. there's not smooth shading at all, and this happens with any of the 5 different shaders i've tried to use. i have to note that i tried used shaders i found over the internet, then made my own using shaderFX in max, all ending up in the same result...

standard d3d pipeline:
[attachment=1887:d3dpipeline.jpg]

simple diffuse shader:
[attachment=1888:shader.jpg]

i've made sure the normals are imported correctly, i've also tried different computers/drivers, all the same.

btw the models are from nfs shift 2.

has anyone seen anything like that before? any ideas/tips?

toon shading is really not what i want to do right now :D

Share this post


Link to post
Share on other sites
Ron AF Greve    900
Maybe you accidentally (although unllikely) use fixed pipeline? Try

[code]
DeviceInterface->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
[/code]
and see if that solves the problem.

Share this post


Link to post
Share on other sites
vagos21    122
I've tried turning on/off all my initialisation parameters to see what's happening but nothing changed. since we'd reach a point when i'd have to show what's done, here's my current initialisation:

[code]
graphicsDevice.RenderState.ZBufferEnable = True
graphicsDevice.RenderState.Lighting = True
With graphicsDevice.SamplerState(0)
.MinFilter = TextureFilter.Linear
.MagFilter = TextureFilter.Linear
End With
With graphicsDevice.Lights(0)
.Type = LightType.Directional
.Diffuse = System.Drawing.Color.White
.Ambient = System.Drawing.Color.Black
.Specular = System.Drawing.Color.White
.Position = New Vector3(5.0F, 5.0F, 1.0F)
.Direction = New Vector3(-2.0F, -3.0F, -1.0F)
.Enabled = True
.Update()
End With
[/code]

the way i pass a value to the shader is through a handle:
[code]
carShader = Effect.FromFile(graphicsDevice, Application.StartupPath & "\diffuse.fx", Nothing, Nothing, ShaderFlags.None, Nothing)
h_tech = carShader.GetTechnique("Complete")
carShader.Technique = h_tech
h_WorldViewProj = carShader.GetParameter(Nothing, "wvp")
carShader.SetValue(h_WorldViewProj, tempmatrix)
[/code]

and render loop is something like:
[code]
graphicsDevice.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, System.Drawing.Color.Gray, 1.0F, 0)
graphicsDevice.BeginScene()
<here i pass matrices and light position to the shader>

'then i loop through all the primitives of all the meshes (mesh,prim)
graphicsDevice.SetStreamSource(0, myscene.meshes(mesh).vb, 0)
graphicsDevice.Indices = myscene.meshes(mesh).ib(prim)
Dim numpasses As Integer = carShader.Begin(FX.DoNotSaveShaderState)
For pass As Integer = 0 To numpasses - 1
carShader.BeginPass(pass)
m.DrawSubset(0)
graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numverts, 0, numfaces)
carShader.EndPass()
Next
carShader.End()

graphicsDevice.EndScene()
graphicsDevice.Present()
[/code]

i really can't trace where the problem is...
Edit: i just tried with a teapot mesh in case it was a normals problems, but it's doing exactly the same thing.

Share this post


Link to post
Share on other sites
Ron AF Greve    900
I usually just use one or two triangles by hand when debugging a shader. Are you sure the normals are ok? Every vertex should have actually one normal (so it tyically is not the normal of the plane that the triangle lies in). So every triangle should have three different normals.if the two triangles share an edge you would end up with 3 different normals (assuming the triangles are not in the same plane).



Share this post


Link to post
Share on other sites
unbird    8338
You set fixed function parameters (GraphicsDevice.Lights(0)) and then use a shader. If you use a shader you have to provide all information through shader parameters (material, light, etc), just like you set the wvp parameter now.

I assume the latter is correct (tempmatrix), since the rendering at least transforms the car correctly. But for lighting you (normally) have to submit also the world (or world inverse transpose) matrix to transform the normals correctly. Currently, we only see you set one shader parameter. Anyway, we don't know for sure what your shader expects. Could you please show us the full diffuse.fx shader code please - or at least the shaders from that "Complete" technique - and all the parameters you set ? That should clarify things.

Also: When working with shaders, get back the error string. Even if it compiles, there might be relevant warnings.

As an aside, this is a bit weird:
[code]
m.DrawSubset(0)
graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numverts, 0, numfaces)
[/code]
As I understand you draw the same thing twice. This is superflous. Either use Mesh.DrawSubset or a (manual) DrawIndexPrimitive.

Also: If you don't already know: With PIX you can debug your rendering quite fine.

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