How to set HLSL constant table without D3DX in D3D9
D3DXCompileShader is too slow.
IDirect3DDevice9::CreatePixelShader from .cso file works. But I still need to use IDirect3DPixelShader9::GetFunction?D3DXGetShaderConstantTable to get ID3DXConstantTable.
Since D3DX static library in Summer 2004 version is a little large, and later version will introduce dependency of d3dx9_xx.dll, is there any way to set HLSL constant table without D3DX in D3D9
The HLSL constant table is at a much higher level of abstraction than is provided by the raw API: the constant table doesn't actually really "exist" at all in a shader.
In reality the D3DX stuff is just an elaborate software wrapper around:
float4 myConstant : register(c0); // HLSL declaration, this constant is using register 0
Device->SetVertexShaderConstantF (0, data, 1); // C++ code to set the constant
Where the "0" in SetVertexShaderConstantF matches the "c0" in the HLSL declaration, "data" is an array of 4 floats and "1" is the number of float4s to set.
When working without D3DX you need to forget about all of the helper infrastructure it builds around a shader and just do it this way instead.
The HLSL constant table is at a much higher level of abstraction than is provided by the raw API: the constant table doesn't actually really "exist" at all in a shader.
In reality the D3DX stuff is just an elaborate software wrapper around:float4 myConstant : register(c0); // HLSL declaration, this constant is using register 0
Device->SetVertexShaderConstantF (0, data, 1); // C++ code to set the constant
Where the "0" in SetVertexShaderConstantF matches the "c0" in the HLSL declaration, "data" is an array of 4 floats and "1" is the number of float4s to set.
When working without D3DX you need to forget about all of the helper infrastructure it builds around a shader and just do it this way instead.
Thank you very much. I will try it.
So, setting constant has nothing to do with the shader buffer?
Device->SetVertexShaderConstantF will directlt set the value to GPU register?
But another question:
What does the first parameter of D3DXGetShaderConstantTable do?
ID3DXConstantTable->SetFloat could be implemented like Device->SetVertexShaderConstantF, What is pFunction?
Why not modify D3DXGetShaderConstantTable to D3DXGetShaderConstantTable(IDirect3DDevice9 *, ID3DXConstantTable **)?
How to draw text without D3DX?
What does D3DXFont do?
I have an idea:
1, Create GDI bitmap;
2, Draw text by GDI; (draw onto white backgound and then onto black background to calculate alpha if neccessary)
3, Create D3D9 texture and copy the bits;
4, Draw the texture in D3D9, adjust the alignment by DT_*.
Will it be OK?
As an alternative, you can pre-generate a "font texture" that contains all of the glyphs that you need. You can then render your strings by drawing a one quad per character, with each quad having the appropriate texture coordinates for whichever character that they represent. There are even free tools available for generating these font textures:
https://github.com/andryblack/fontbuilder
http://www.angelcode.com/products/bmfont/
https://github.com/nothings/stb/blob/master/stb_truetype.h
An alternative to dumping D3DX is to dynamically link to it instead. For the most part the API remains the same, so your expectation should be that more recent versions of the D3DX DLLs primarily contain bugfixes and performance improvements. With that in mind, your procedure is:
- Begin a loop counting from 43 down to 24 (this is based on the D3DX DLLs on my own PC; 23 and below were the static library versions).
- Construct the DLL name from loop counter: sprintf (dllname, "d3dx9_%i.dll", version);
- Call LoadLibrary on it, if LoadLibrary fails then go to the next iteration (if there is no next iteration error out), otherwise continue.
- Call GetProcAddress on the D3DX entry points you need to use using the HINSTANCE of the successfully loaded library.
There's a bit more work involved in this as you'll need to declare types for your GetProcAddress returns, but it will let your program be quite D3DX-version-agnostic, and is also future-proofed a little better in that you'll be able to successfully upgrade your project to newer versions of Visual Studio which don't come with the D3DX libs (and which may fail to compile when linking against the old SDKs).
That is essentially what D3DXFont does under the hood.
As an alternative, you can pre-generate a "font texture" that contains all of the glyphs that you need. You can then render your strings by drawing a one quad per character, with each quad having the appropriate texture coordinates for whichever character that they represent. There are even free tools available for generating these font textures:
https://github.com/andryblack/fontbuilder
http://www.angelcode.com/products/bmfont/
https://github.com/nothings/stb/blob/master/stb_truetype.h
It seems to be a good method on English language. Unfortunately most of my target system is in Chinese language (zh-cn). It is not a simple task to render each character to textures. That's a too large collection.
An alternative to dumping D3DX is to dynamically link to it instead. For the most part the API remains the same, so your expectation should be that more recent versions of the D3DX DLLs primarily contain bugfixes and performance improvements. With that in mind, your procedure is:
There's a bit more work involved in this as you'll need to declare types for your GetProcAddress returns, but it will let your program be quite D3DX-version-agnostic, and is also future-proofed a little better in that you'll be able to successfully upgrade your project to newer versions of Visual Studio which don't come with the D3DX libs (and which may fail to compile when linking against the old SDKs).
- Begin a loop counting from 43 down to 24 (this is based on the D3DX DLLs on my own PC; 23 and below were the static library versions).
- Construct the DLL name from loop counter: sprintf (dllname, "d3dx9_%i.dll", version);
- Call LoadLibrary on it, if LoadLibrary fails then go to the next iteration (if there is no next iteration error out), otherwise continue.
- Call GetProcAddress on the D3DX entry points you need to use using the HINSTANCE of the successfully loaded library.
d3d9_xx.dll does not exists in Windows XP SP3...