Can I calculate global variable in HLSL before vertex shader applied? - hlsl

there are three global variable g_A, g_B, g_C
I want to do this; g_C = g_A * g_B
I tried this;
technique RenderScene
{
g_C = g_A * g_B;
pass P0
{
VertexShader = compile vs_2_0 RenderSceneVS();
PixelShader = compile ps_2_0 RenderScenePS();
}
}
However, it's improper syntax.
What should I do?
Must I calculate this variable in c++ code before rendering?

DirectX 9 and 10 Effects support "preshaders", where static expressions will be pulled out to be executed on the CPU automatically.
See D3DXSHADER_NO_PRESHADER in the documentation, which is a flag that suppresses this behavior. Here's a web link: http://msdn.microsoft.com/en-us/library/windows/desktop/bb205441(v=vs.85).aspx
Your declaration of g_C is missing both static and the type e.g. float. You'll also need to move it into global scope.
When you compile it with fxc, you might see something like the following (note the preshader block after the comment block):
technique RenderScene
{
pass P0
{
vertexshader =
asm {
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
// Parameters:
//
// float4 g_A;
// float4 g_B;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// g_A c0 1
// g_B c1 1
//
preshader
mul c0, c0, c1
// approximately 1 instruction used
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
vs_2_0
mov oPos, c0
// approximately 1 instruction slot used
};
pixelshader =
asm {
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
ps_2_0
def c0, 0, 0, 0, 0
mov r0, c0.x
mov oC0, r0
// approximately 2 instruction slots used
};
}
}
I compiled the following:
float4 g_A;
float4 g_B;
static float4 g_C = g_A * g_B;
float4 RenderSceneVS() : POSITION
{
return g_C;
}
float4 RenderScenePS() : COLOR
{
return 0.0;
}
technique RenderScene
{
pass P0
{
VertexShader = compile vs_2_0 RenderSceneVS();
PixelShader = compile ps_2_0 RenderScenePS();
}
}
with fxc /Tfx_2_0 t.fx to generate the listing. They're not very interesting shaders...

Related

how to use a fragment shader without main function

i found a shader to do a drop shadow from http://madebyevan.com/shaders/fast-rounded-rectangle-shadows/
// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
// This approximates the error function, needed for the gaussian integral
vec4 erf(vec4 x) {
vec4 s = sign(x), a = abs(x);
x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
x *= x;
return s - s / (x * x);
}
// Return the mask for the shadow of a box from lower to upper
float boxShadow(vec2 lower, vec2 upper, vec2 point, float sigma) {
vec4 query = vec4(point - lower, upper - point);
vec4 integral = 0.5 + 0.5 * erf(query * (sqrt(0.5) / sigma));
return (integral.z - integral.x) * (integral.w - integral.y);
}
i thought that a shader need a main function and should return color.
My question is how to use the function boxShadow in c++ code with opengl given a box
thanks
A function can be defined in a shader just as you would do with a C function. I mean, the code for the function is in the same "unit" as the rest of the shader.
#version XX-YY
//MyFunc(.....)
whateverreturn MyFunc(.....)
{
do something and return a whateverreturn
}
void main(void)
{
//use MyFunc
whateverreturn var = MyFunc(....)
}
A bit different case is when you have a function that can be part of several shaders, but it isn't a "full" shader, it has no main() function. This function lives in a file or in string-array or something similar.
Say you have the function in a specific file:
#version XX-YY
//MyFunc(.....)
whateverreturn MyFunc(.....)
{
do something and return a whateverreturn
}
And the file with the shader where you want to use it:
#version XX-YY
//declare the function
whateverreturn MyFunc(.....);
void main(void)
{
//use MyFunc
whateverreturn var = MyFunc(....)
}
Like you do with any common GLSL code, use glShaderSource and glCompileShader.
Now the key step is how to integrate the code within a full (with 'main') shader: just use glAttachShader (again, like you do with VS or FS) before glLinkProgram and that'as all.

Can't compile HLSL Hull shader code

Here's a simple hull shader code that i made, to try to understand tessellation.
I just can't find anything wrong with this code, but the compile function always return false. Here's my code:
My input and output structures:
[domain("tri")] // indicates a triangle patch (3 verts)
[partitioning("fractional_odd")] // fractional avoids popping
// vertex ordering for the output triangles
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
// name of the patch constant hull shader
[patchconstantfunc("ConstantsHS")]
//[maxtessfactor(7.0)]
cbuffer TessellationBuffer
{
float tessellationAmount;
float3 padding;
};
struct VS_CONTROL_POINT_OUTPUT
{
float3 vWorldPos : POSITION;
float2 vTexCoord : TEXCOORD0;
float3 vNormal : NORMAL0;
};
struct HS_CONTROL_POINT_OUTPUT
{
float3 vWorldPos : POSITION;
float2 vTexCoord : TEXCOORD0;
float3 vNormal : NORMAL0;
};
struct HS_CONSTANT_DATA_OUTPUT
{
float Edges[3] : SV_TessFactor;
float Inside : SV_InsideTessFactor;
};
My functions:
HS_CONTROL_POINT_OUTPUT HS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint uCPID : SV_OutputControlPointID, uint patchId : SV_PrimitiveID )
{
HS_CONTROL_POINT_OUTPUT Output;
Output.vWorldPos = inputPatch[uCPID].vWorldPos;
Output.vTexCoord = inputPatch[uCPID].vTexCoord;
Output.vNormal = inputPatch[uCPID].vNormal;
return Output;
};
HS_CONSTANT_DATA_OUTPUT ConstantsHS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint PatchID : SV_PrimitiveID )
{
HS_CONSTANT_DATA_OUTPUT Output;
Output.Edges[0] = tessellationAmount;
Output.Edges[1] = tessellationAmount;
Output.Edges[2] = tessellationAmount;
Output.Inside = tessellationAmount;
return Output;
};
Thanks for any help.
The attributes have to be set on the entry point like below, then your hull shader is valid :
[domain("tri")] // indicates a triangle patch (3 verts)
[partitioning("fractional_odd")] // fractional avoids popping
// vertex ordering for the output triangles
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
// name of the patch constant hull shader
[patchconstantfunc("ConstantsHS")]
//[maxtessfactor(7.0)]
HS_CONTROL_POINT_OUTPUT HS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint uCPID : SV_OutputControlPointID, uint patchId : SV_PrimitiveID )
On a side note, The command line tool FXC.exe would have print an error message that would have put you in the right direction : error X3000: syntax error: unexpected token 'cbuffer'
And i am unsure of what function you are referring to, D3DCompile return a HRESULT, not a boolean, and it also output a blob for you with the error messages in case of failure.

Shaders and Directx11 compilation in c++

I am trying to create a Directx 11 program using c++ . The code used to work before I added Normal to the code .Now it doesnt compile the shader at all .It keeps giving me access Violation 0X0000 Error.
I tried using d3dErrorBlolb but wasnt very helpful.The problem seems to lie in this part of the code.
void InitPipeline(HWND hwnd)
{
ID3D10Blob * BVS = 0,*BPS = 0;
ID3D10Blob * BErrorVS,*BErrorPs;
HRESULT hr1 = D3DX11CompileFromFile(L"Test.fx",0,0,"VS","vs_4_0",0,0,0,&BVS,&BErrorVS,0);
HRESULT hr = D3DX11CompileFromFile(L"Test.fx",0,0,"PS","ps_4_0",0,0,0,&BPS,&BErrorPs,0);
if(FAILED(hr))
{
printf("Error %08X %5s\n",hr,(char*)BErrorVS);
MessageBox(hwnd,L"Pixel shader not created ",L"",0);
}
if(FAILED(hr1))
{ MessageBox(hwnd,L"Vertex shader not created ",L"",0);}
dev->CreateVertexShader(BVS->GetBufferPointer(),BVS->GetBufferSize(),0,&BoxVShader);
dev->CreatePixelShader(BPS->GetBufferPointer(),BPS->GetBufferSize(),0,&BoxPixelShader);
// create the input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0}
// {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
//SecureZeroMemory(&Bin);
dev->CreateInputLayout(ied,2,BVS->GetBufferPointer(),BVS->GetBufferSize(),&BInputLayout);
devcon->VSSetShader(BoxVShader,0,0);
devcon->PSSetShader(BoxPixelShader,0,0);
devcon->IASetInputLayout(BInputLayout);
}
The Test.fx file
ecbuffer ConstantBuffer:register(b0)
{
matrix world;
matrix view;
matrix project;
float3[2] LightDir;
float4[2] LightColor;
}
struct Vout{
float4 pos:SV_POSITION;
float4 normal : NORMAL;
};
Vout VS(float3 pos:POSITION,float3 Norm:NORMAL)
{
Vout vo = (Vout)0;
vo.pos = mul(float4(pos,1),world);
vo.pos = mul(vo.pos,view);
vo.pos = mul(vo.pos,project);
vo.normal = mul(float4(Norm,1),world);
return vo;
}
float4 PS(float4 pos:SV_POSITION,float4 normal:NORMAL):SV_TARGET
{
float4 col;
for(int i=0; i < 2;++i)
{
col += saturate(dot(normal,LightDir[i])) * LightColor[i] ;
}
return col;
}
Can anyone please be kind enough to help me out...
If possible please do explain why this keeps happening always..What am I doing wrong here
Please do help me.I desperately need to solve this problem....
Thank you...
While compiling HLSL at runtime is nice for learning and iteration, it's actually a lot easier to debug the HLSL by compiling it with the command-line:
fxc test.fx /Tvs_4_0 /EVS and fxc test.fx /Tps_4_0 /EPS
The second fails because you failed to set the initial value for col in the Pixel Shader:
test.fx(40,25-47): warning X3206: 'dot': implicit truncation of vector type
test.fx(40,9-64): error X4000: variable 'col' used without having been completely initialized
compilation failed; no code produced
The fix is trivial:
float4 PS(float4 pos:SV_POSITION,float4 normal:NORMAL):SV_TARGET
{
float4 col = 0;
for(int i=0; i < 2;++i)
{
col += saturate(dot(normal,LightDir[i])) * LightColor[i] ;
}
return col;
}
You are getting an AV because you have the wrong handling of the failed compiler output, you forgot to initialize both BErrorVS and BErrorPS to null, and you are trying to output BErrorVS when the VS succeeded, but the PS failed. It should be:
if(FAILED(hr))
{
printf("Error %08X %5s\n",hr,(char*)BErrorPS->GetBufferPointer());
MessageBox(hwnd,L"Pixel shader not created ",L"",0);
}
Also you should remember that BErrorVS and BErrorPS can be set to a non-null value even if SUCCEEDED(hr)) since it can be reporting only non-fatal warnings.
See HLSL, FXC, and D3DCompile

CgFx compiler error "Unknown state 'VertexShader'"

I' have the following CgFx file:
struct VertIn {
float4 pos : POSITION;
float4 color : COLOR0;
};
struct VertOut {
float4 pos : POSITION;
float4 color : COLOR0;
};
VertOut vert(VertIn IN) {
VertOut OUT;
OUT.pos = IN.pos;
OUT.color = IN.color;
OUT.color.z = 0.0f;
return OUT;
}
struct FragIn {
float4 color: COLOR;
};
struct FragOut {
float4 color : COLOR;
};
FragOut frag(FragIn IN) {
FragOut OUT;
OUT.color = IN.color;
OUT.color.y = 0.0f;
return OUT;
}
struct GeomIn {
float4 position : POSITION;
float4 color : COLOR0;
};
TRIANGLE void geom(AttribArray<GeomIn> IN) {
for(int i=0; i<IN.length; i++) {
emitVertex(IN[i]);
}
}
technique technique0 {
pass p0 {
VertexShader = compile gp4vp vert(); //line 47
FragmentShader = compile gp4fp frag(); //line 48
GeometryShader = compile gp4gp geom(); //line 49
}
}
when using cgc to verify the 3 shaders, they all compile fine.
but when I try to compile the whole effect using:
context=cgCreateContext();
effect=cgCreateEffectFromFile(context, "my_shader.cgfx", NULL);
if(!effect) {
printf(ygl.cgGetLastErrorString(NULL));
printf(cgGetLastListing(context));
}
then I get the following errors:
CG ERROR : The compile returned an error.
my_shader.cgfx(47) : error C8001: Unknown state 'VertexShader'
my_shader.cgfx(48) : error C8001: Unknown state 'FragmentShader'
my_shader.cgfx(49) : error C8001: Unknown state 'GeometryShader'
What do I do wrong?
After creating your context, you need to call
cgGLRegisterStates(handle);
where handle is your CG context handle. This will register things like VertexShader, PixelShader, FillMode, etc. I'm not sure why those aren't registered by default, but there you have it.
well, solved it, but don't know how. I think the compiler didn't expect CgFx because i did load a cg profile earlier, so it tried to use that one. but not sure.

enable/disable frag & vert shaders

Currently I'm using
glUseProgramObjectARB(ProgramObject);
and
glUseProgramObjectARB(0);
But it doesn't switch back properly,and gives me an “invalid operation glError” along these lines
void updateAnim_withShader()
{
int location;
location = getUniLoc(ProgramObject, "currentTime");
ParticleTime += 0.002f;
if (ParticleTime > 15.0)
ParticleTime = 0.0;
glUniform1fARB(location, ParticleTime);
printOpenGLError();
}
What's the proper/right way of doing it(enable/disable shaders)?
[my code files(Temporary link removed )][1]
Your location is -1, because the actual currentTime uniform was not used in a shader.