simple vertex shader stuff
Hey, I'm trying to get into this whole shader business, but I'm confused.
All I want this one to do is set the diffuse color to green
// setup shader
DWORD dwDecl[] = {
D3DVSD_STREAM(0),
D3DVSD_REG(0, D3DVSDT_FLOAT3 ), //input register v0
D3DVSD_REG(5, D3DVSDT_D3DCOLOR ), // input register v5
D3DVSD_REG(7, D3DVSDT_FLOAT2 ), // input register v7
D3DVSD_REG(8, D3DVSDT_FLOAT2 ), // input register v7
D3DVSD_END()
};
// the vertices im using use(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2)
// set constants
FLOAT fMaterial[4] = {0,1,0,0};
d->SetVertexShaderConstant(5, fMaterial, 1);
// define shader
const char BasicVertexShader[] =
"vs.1.1 \n""mov oD0, c5 \n";
// create shader
ID3DXBuffer *pVs;
DWORD shader;
D3DXAssembleShader(BasicVertexShader, sizeof(BasicVertexShader) - 1, 0, NULL, &pVs, NULL);
d->CreateVertexShader(dwDecl, (DWORD*)pVs->GetBufferPointer(), &shader, 0 );
d->SetVertexShader( shader );
// end
I do all of that in the initialization function, if that helps.
It doesn't change a damn thing.
PS - there is a backslash in between the vs.1.1 and the mov instructions, but the forum erases it. Just so you know it's not that.
[edited by - Funkymunky on January 5, 2004 10:22:23 AM]
SetVertexShaderConstant passes the color to an constant register (c5 in your case). You don''t need to hand-pass the color to the shader, if you want to use the color, stored in your vertex-buffer. Just map the color to an input-register of you choice. That''s at least, how it works in DX9.
Hope this helps. ;-)
Hope this helps. ;-)
Ok, but shouldn't what I wrote work? And I don't necessarily want to use the color in the vertex buffer, because what would be the point of using a shader at all then? I'm just trying to get it to alter something.
What's that, like since i called D3DVSD_REG(5, D3DVSDT_D3DCOLOR), use "mov oD0, v5" ?
Again, I'm just trying to get a grasp on them, and since the one I posted doesn't do anything even though I thought it would, I was hoping for some insight.
But thanks! any more help?
PS - if you guys think it should work too and that's why you aren't posting, then let me know that! Right now it seems like noone knows vertex shaders
[edited by - Funkymunky on January 5, 2004 10:15:53 AM]
quote:Just map the color to an input-register of you choice
What's that, like since i called D3DVSD_REG(5, D3DVSDT_D3DCOLOR), use "mov oD0, v5" ?
Again, I'm just trying to get a grasp on them, and since the one I posted doesn't do anything even though I thought it would, I was hoping for some insight.
But thanks! any more help?
PS - if you guys think it should work too and that's why you aren't posting, then let me know that! Right now it seems like noone knows vertex shaders
[edited by - Funkymunky on January 5, 2004 10:15:53 AM]
Your shader is too simple. Your shader must do everything the fixed pipe did that you want to replace.
You''ve set the color just fine, but you never set the output vertex position, or texture coordinates. Also if you''ve got blending enabled you might want to change the alpha from 0.
Take your world, view, and projection matrices, mutltiply them, transpose the result and put in into some constants.
Ideally you''ll merge that set constant call with your color one, as this function actually runs incredibly slowly.
Now you''ll make some additions to your shader. We want to multiply your vertex by world, view, projection. We''ll move the color as you had it. We''ll move the texture coordinates down the pipeline too, without texture coordinate transforms, just simply passing them along.
Hope this helps.
You''ve set the color just fine, but you never set the output vertex position, or texture coordinates. Also if you''ve got blending enabled you might want to change the alpha from 0.
Take your world, view, and projection matrices, mutltiply them, transpose the result and put in into some constants.
D3DXMATRIX wvp, wvpt;wvp = world * view * projection;D3DXMatrixTranspose(&wvpt, &wvp);dev->SetVertexShaderConstant(0, &wvpt, 4);
Ideally you''ll merge that set constant call with your color one, as this function actually runs incredibly slowly.
Now you''ll make some additions to your shader. We want to multiply your vertex by world, view, projection. We''ll move the color as you had it. We''ll move the texture coordinates down the pipeline too, without texture coordinate transforms, just simply passing them along.
"vs.1.1\n""dp4 oPos.x, v0, c0\n""dp4 oPos.y, v0, c1\n""dp4 oPos.z, v0, c2\n""dp4 oPos.w, v0, c3\n""mov oD0, c5\n""mov oT0, v7\n""mov oT1, v8\n"
Hope this helps.
Damn, well at least it did something...now nothing is drawn. I figured out that I had a SetVertexShader call already, using my FVF flags. I hadn''t realized I''d been using this all along. That''s why nothing was being changed, i wasn''t even applying the vertex shader.
So, I have to keep track of my three matrices at all times if I want to use Vertex Shaders? Do I need to update the vertex shader each frame?
Thanks, that helps a lot, but i''m still quite confused!
So, I have to keep track of my three matrices at all times if I want to use Vertex Shaders? Do I need to update the vertex shader each frame?
Thanks, that helps a lot, but i''m still quite confused!
Yes, you need to keep track of your matrices at all times. You might have your view and projection matrices in a camera class, and you might have a global pointer to the current camera. You might also have view*projection already computed, once per frame (or camera move), do reduce the number of matrix multiplies you need. In more complex shaders you may want world, view, and projection as seperate matrices, for such things as lighting, and texture coordinate generation.
I don''t think you need to set the shader each frame if you haven''t changed shaders/fvfs, but it won''t hurt. Generally I treat a new frame as if it''s from scratch. I set textures, shaders, render states to some default known value each frame, or just mark my currently cached values as invalid. Then I skip redundant textures, shaders, and states for the rest of the frame. Nothing can get too screwed up that way.
The SDK has a some samples using shaders... Maybe it would be a good place to check for whatever else you''re missing.
I don''t think you need to set the shader each frame if you haven''t changed shaders/fvfs, but it won''t hurt. Generally I treat a new frame as if it''s from scratch. I set textures, shaders, render states to some default known value each frame, or just mark my currently cached values as invalid. Then I skip redundant textures, shaders, and states for the rest of the frame. Nothing can get too screwed up that way.
The SDK has a some samples using shaders... Maybe it would be a good place to check for whatever else you''re missing.
Damn. Alright that helps, but it still doesn''t draw anything!
now it''s like this:
first these are private variables in the class:
and this is in the initialization function, called once
and here''s the basic render loop
shouldn''t that work?!
now it''s like this:
first these are private variables in the class:
ID3DXBuffer *pVs; DWORD shader;
and this is in the initialization function, called once
// setup shader DWORD dwDecl[] = { D3DVSD_STREAM(0), D3DVSD_REG(0, D3DVSDT_FLOAT3 ), //input register v0 D3DVSD_REG(5, D3DVSDT_D3DCOLOR ), // input register v5 D3DVSD_REG(7, D3DVSDT_FLOAT2 ), // input register v7 D3DVSD_REG(8, D3DVSDT_FLOAT2 ), // input register v7 D3DVSD_END() };// transformation stuff D3DXMATRIX w, v, p; d->GetTransform(D3DTS_WORLD, &w); d->GetTransform(D3DTS_VIEW, &v); d->GetTransform(D3DTS_PROJECTION, &p); D3DXMATRIX wvp, wvpt; wvp = w * v * p; D3DXMatrixTranspose(&wvpt, &wvp);// set constants FLOAT fMaterial[4] = {0,1,0,0}; d->SetVertexShaderConstant(5, fMaterial, 1); d->SetVertexShaderConstant(0, &wvpt, 4);// define shader const char BasicVertexShader[] = "vs.1.1 \n"\ "dp4 oPos.x, v0, c0\n"\ "dp4 oPos.y, v0, c1\n"\ "dp4 oPos.z, v0, c2\n"\ "dp4 oPos.w, v0, c3\n"\ "mov oD0, c5\n"\ "mov oT0, v7\n"\ "mov oT1, v8\n";// create shader if(D3DXAssembleShader(BasicVertexShader, sizeof(BasicVertexShader) - 1, 0, NULL, &pVs, NULL) != D3D_OK) return false; if(d->CreateVertexShader(dwDecl, (DWORD*)pVs->GetBufferPointer(), &shader, 0 ) != D3D_OK) return false;
and here''s the basic render loop
d->SetStreamSource(0, vbuffer, sizeof(LandVertex)); d->SetVertexShader( shader ); d->SetIndices(ibuffer, 0); d->SetTexture(0, texture); d->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, numverts, 0, numtriangles); d->SetTexture(0, NULL);
shouldn''t that work?!
quote:Original post by Funkymunky
Damn. Alright that helps, but it still doesn't draw anything!
now it's like this:...d->GetTransform(D3DTS_WORLD, &w);d->GetTransform(D3DTS_VIEW, &v);d->GetTransform(D3DTS_PROJECTION, &p);...
Hmmm. Looks okay. Does you card support shaders? Do the creation calls succeed or fail? Are you using a pure device? The get functions above won't work if it's pure. Have you actually set all 3 matrices? Often, people set world in their render routine. Since you're replacing your render routine with a new one, do you still set the world matrix? And as I pointed out at the beginning, if you've got alphablending or alphatesting enabled you might have trouble since you set the alpha to 0.
Now this next part isn't going to solve your problem, but... D3D no longer needs the world or view matrices to be set using SetTransform(), only the shader needs them. D3D needs projection to be set only for fogging to work correctly. Again, it doesn't hurt to pass them to D3D, but it's not strictly necessary... As such, using GetTransform() is a bad way to code this, as it means you MUST give the transforms to D3D even though it doesn't need them, and it means you cannot use a pure device.
edit:
Noticed you're only building and setting the constants at init time. Are ANY of your 3 matrices set up at this point? Building and setting the matrices are both typically part of the render loop.
[edited by - namethatnobodyelsetook on January 5, 2004 2:38:28 PM]
Yes my card supports shaders.
The calls succeed.
Whaddya mean a pure device? i created it with
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
(standard stuff)
yes I set all three matrices. I only make the projection and world matrices once in initialization (before initializing the object which uses the shader) and I update the view matrix each frame through my camera object.
No alpha blending.
The calls succeed.
Whaddya mean a pure device? i created it with
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
(standard stuff)
yes I set all three matrices. I only make the projection and world matrices once in initialization (before initializing the object which uses the shader) and I update the view matrix each frame through my camera object.
No alpha blending.
Ok, you''re not using a pure device (it would go where you have D3DCREATE_SOFTWARE_VERTEXPROCESSING).
I''ve never used a shader in software mode. Either create a hardware device, or try D3DUSAGE_SOFTWAREPROCESSING in your CreateVertexShader() call, and see if that fixes anything... Preferably changing your device to hardware, since I don''t know how the software shader emulation works.
Since you''re setting your view matrix per frame, you still need to move your "w*v*p calculation, transposing, and programming into constants" code, into the render loop.
I''ve never used a shader in software mode. Either create a hardware device, or try D3DUSAGE_SOFTWAREPROCESSING in your CreateVertexShader() call, and see if that fixes anything... Preferably changing your device to hardware, since I don''t know how the software shader emulation works.
Since you''re setting your view matrix per frame, you still need to move your "w*v*p calculation, transposing, and programming into constants" code, into the render loop.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement