code style

3/30/2007

Irradiance Environment Map

Radiance is the emitted energy per unit time in a given direction from a unit area of an emitting surface. We can capture radiance at a point for all directions by rendering a cube map, A.K.A. radiance distribution function. The radiance of a purely diffuse surface is defined in terms of surface's irradiance.

The irradiance distribution function at a point can be stored using a diffuse cube map, also called irradiance environment map. At SIGGRAPH 2001, Ramamoorthi and Hanrahan proposed a technique to represent irradiance environment map by Spherical Harmonics. This reduces both the storage and bandwidth costs.



DirectX SDK provides functions for projecting a cube map into spherical harmonic coefficients as well as other SH operation functions. SH is a kind of frequency space transformation likes Fourier transformation, but on spherical space. Ramamoorthi found 3rd order SH effectively represents the irradiance distribution function. 3rd order SH only needs 9 floating point coefficients per channel, i.e. R, G, B.



Reference

3/21/2007

中永和之歌

永和有永和路,中和也有永和路, 中和有中和路,永和也有中和路; 中和的中和路有接永和的中和路, 永和的永和路沒接中和的永和路; 永和的中和路有接永和的永和路, 中和的永和路沒接中和的中和路。

永和有中正路,中和也有中正路, 永和的中正路用景平路接中和的中正路; 永和有中山路,中和也有中山路, 永和的中山路直接接上了中和的中山路。 永和的中正路接上了永和的中山路, 中和的中正路卻不接中和的中山路。

這就是我居住的城市: 中正橋下來不是中正路,但永和有中正路; 秀朗橋下來也不是秀朗路,但永和也有秀朗路。 永福橋下來不是永福路,永和沒有永福路; 福和橋下來也不是福和路,但福和路接的卻是永福橋。 這是什麼地方?百慕達三角洲嗎? 難怪我常常鬼打牆阿...


中永和 - Uncyclopedia - 偽基百科

3/16/2007

Using DirectX with wxWidget

wxWidgets A.K.A. wxWindow is a cross-platform toolkit for creating window application. There is a class called wxGLCanvas for OpenGL, but no information for DirectX. Then, I try to integrate DirectX with wxWidgets. I found flick will happen when I use paint event to draw d3d frame. To avoid from flicking, I use erase event to clear the background of window and redraw d3d frame. Here is the pseudo code:

class MyApp : public wxApp {
virtual bool OnInit();
virtual int OnExit();
};
class MyViewport : public wxPanel {
public:
MyViewport(wxWindow* parent);
void OnIdle(wxIdleEvent& event);
void OnDraw(wxEraseEvent& event);
private:
DECLARE_EVENT_TABLE()
};

class MyFrame: public wxFrame {
MyViewport *mpViewport;
public:
MyFrame(const wxString& title);
private:
DECLARE_EVENT_TABLE()
};

// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(MyViewport, wxPanel)
EVT_ERASE_BACKGROUND (MyViewport::OnDraw)
EVT_IDLE (MyViewport::OnIdle)
END_EVENT_TABLE()

// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also implements the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and not wxApp)
IMPLEMENT_APP(MyApp)

// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit() {
// create the main application window
MyFrame *frame = new MyFrame( _T("D3D sample") );

create D3D device here

frame->Show(true);
SetTopWindow(frame);
return true;
}

int MyApp::OnExit() {
release D3D device here

return wxApp::OnExit();
}

// frame constructor
MyFrame::MyFrame(const wxString& title) :
wxFrame(NULL, -1, title, wxPoint(0,0)), mpViewport(NULL), mpTreeCtrl(NULL)
{
mpViewport = new MyViewport(this);
}

MyViewport::MyViewport(wxWindow* parent) : wxPanel(parent) {
}

void MyViewport::OnIdle(wxIdleEvent& event) {
update your d3d objects here

// call Refresh() to send a wxEraseEvent to redraw a frame
Refresh();
}

void MyViewport::OnDraw(wxEraseEvent& event) {
g_pd3dDevice->BeginScene();

draw your d3d objects here

g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL,NULL, this->GetHWND() ,NULL);
}

抖腳

本人常常因為抖腳而被女友罵

結果今天在公司看到外國人坐在位子上抖腳

果然抖腳是男人的天性 中外皆然 XD

3/09/2007

How to write a directx shader for 3dsmax


Since programmable GPU was appeared, many and many game engines have to support this feature to create more and more visual effects. And also, 3D modeling softwares need to adapt this new feature.

3dsmax provides a material called "DirectX shader". You can write your directX shader (a.k.a HLSL) and use it as a material in 3dsmax. but there are some rules and restrictions(see DirectX 9 Shader Material-Semantics and Annotations). There are some sample FX files in map\fx\ directory. Let us open the default.fx file.

// This is used by 3dsmax to load the correct parser
string ParamID = "0x0";

//DxMaterial specific
// light direction (view space)
float3 lightDir : Direction < uiname = "Light Direction" object = "TargetLight"> = {-0.577, -0.577, 0.577};

// light intensity
float4 I_a = { 0.1f, 0.1f, 0.1f, 1.0f }; // ambient
float4 I_d = { 1.0f, 1.0f, 1.0f, 1.0f }; // diffuse
float4 I_s = { 1.0f, 1.0f, 1.0f, 1.0f }; // specular

// material reflectivity
float4 k_a < uiname = "Ambient"> = float4( 0.47f, 0.47f, 0.47f, 1.0f ); // ambient
float4 k_d < uiname = "Diffuse"> = float4( 0.47f, 0.47f, 0.47f, 1.0f ); // diffuse
float4 k_s < uiname = "Specular"> = float4( 1.0f, 1.0f, 1.0f, 1.0f ); // diffuse // specular
int n< uiname = "Specular Power" uitype = "IntSpinner" uimin =" 0.0f;" uimax =" 50.0f;"> = 15;

// transformations
float4x4 World : WORLD;
float4x4 View : VIEW;
float4x4 Projection : PROJECTION;
float4x4 WorldViewProj : WORLDVIEWPROJ;
float4x4 WorldView : WORLDVIEW;

struct VS_OUTPUT
{
float4 Pos : POSITION;
float4 col : COLOR0;
};

VS_OUTPUT VS(
float3 Pos : POSITION,
float3 col : COLOR,
float3 Norm : NORMAL,
float2 Tex : TEXCOORD0)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
float3 L = lightDir;
float3 P = mul(float4(Pos, 1),(float4x4)World); // position (view space)
float3 N = normalize(mul(Norm,(float3x3)World)); // normal (view space)
float3 R = normalize(2 * dot(N, L) * N - L); // reflection vector (view space)
float3 V = normalize(P); // view direction (view space)
Out.Pos = mul(float4(Pos,1),WorldViewProj); // position (projected)
float4 Diff = I_a * k_a + I_d * k_d * max(0, dot(N, L)); // diffuse + ambient
float4 Spec = I_s * k_s * pow(max(0, dot(R, V)), n/4); // specular
Out.col = Diff + Spec;
return Out;
}

float4 PS(
float4 Diff : COLOR0,
float4 Spec : COLOR1,
float2 Tex : TEXCOORD0,
float2 Tex1 : TEXCOORD1 ) : COLOR
{
float4 color = Diff + Spec;
return color ;
}

technique DefaultTechnique
{
pass P0
{
// shaders
CullMode = None;
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_1_1 PS();
}
}


DirectX shader material parses the shader file. These variables with 3dsmax specified annotation will create UI components as you can see in "Default.dx Parameters" rollout.
And 3dsmax will pass values to these variables with specified semantic and annotation.
3dsmax use "Direction" as semantic to specify lighting direction. when there is no light in the scene, this parameter use default light's value i.e. current view direction.

The most trick part is we have to assign all mapping channels to vertex shader inputs if we want to use other coordinates such as vertex color, vertex alpha, second texture coordinate...etc.
Else these input value will be disordered and can not get the correct result.

3/08/2007

test

test again