Saturday, June 20, 2009

工作

不知不覺,已經工作了三個星期了。
自由的環境,友好、能幹且寬容的同事,工作環境真的非常不錯!
至於個人的表現,不算太好吧。
雖然我熟悉工作上需要的技術,但還是經常犯錯。
特別是犯了很多小錯誤... 例如:
不小心攪亂SVN
Debug時改了些東西,Release的時候忘記了回復原狀
前幾天才完成的工作,工作上重要的細節,一會兒就忘記了。同事比親自完成工作的我,記得還清楚 Orz...
我發現我的記憶力真的不是一般的弱呀。用同事的術語來說,就是我腦内的Stack非常細,常常overflow。不知是不是嗑藥過多的後遺症?
在這三個星期當中,總算對遊戲開發的過程有了初步的了解。做一個好的production pipeline... 談何容易。

Tuesday, May 12, 2009

Parameters passing between C# and C++/CLI

In C#, parameters can be pass as "ref" or "out".
When writing a C++/CLI library, for the sake of interoperability, we might need to use these features in C++/CLI too.
Mapping:
C# C++/CLI
ref x x% // Managed type reference
out x [System::Runtime::InteropServices::Out] x %

Tuesday, March 10, 2009

Details of how compositor works

The compositor framework hooked into the Ogre rendering pipeline by setting up a RenderTargetListener(CompositorChain).
It is setup when the client call CompositorManager::addCompositor() -> CompositorChain::addCompositor() -> "mViewport->getTarget()->addListener(this);".
It is responsible for registering another listener: RenderQueueListener(CompositorChain::RQListener).

When the "renderQueueStarted" event of RenderQueueListener is fired, it executes all the render operations inside that CompositorChain.
Render operations are represented by the class "CompositorInstance::TargetOperation".
It is the abstract class. The real render operations("clear", "stencil", "quad") are based on it.

The real rendering is executed immediately when CompositorInstance::TargetOperation::execute() is called. For example, in "quad" operation, it sets up the camera, viewport, the full screen quad object, and inject it into the SceneManager and render it.

In the compositor framework, CompositorInstance is just a render operations container, which enqueues the render operations into the CompositorChain. The CompositorChain is the real important class.

Monday, March 9, 2009

GPU Geoclipmap screenshots

Solid mode:

This is Mars

Wire frame:

Grids across 2 faces

Grids across 3 faces

These are the screenshots of my geoclipmap demo.
The algorithm is based on the rectangle geoclipmap [paper link]
The grid of the sphere is indeed a grid cube, which composes of 6 rectangle geoclipmap patches, and the grid cube is then projected into sphere.
The inter-plane cracks are eliminated by my own algorithm. It is quite simple, but it works quite well.
The heightmap sampling and the sphere projection are all done on GPU. Therefore it requires a SM4.0+ GPU to run it.
The shading of the terrain is just a simple height to color mapping. I'm going to implement a more sophisticated shading scheme later. My current focus is to get the partial texture update working, which requires some modifications on Ogre3D.

Thursday, March 5, 2009

The flow of renderOneFrame()

Root::renderOneFrame() -> Root::_updateAllRenderTargets() -> RenderTarget::update() -> Viewport::update() -> Camera::_renderScene() -> SceneManager::_renderScene()

SceneManager::_renderScene()
   \ ->SceneManager::_findVisibleObjects()
   \ ->SceneManager::_renderVisibleObjects() -> SceneManager::_renderQueueGroupObjects() -> SceneManager::renderObjects() -> SceneMgrQueuedRenderableVisitor::visit() -> SceneManager::renderSingleObject()

SceneManager::_renderScene() is the real rendering function.
Most importantly it calls SceneManager::_findVisibleObjects(), which traversals the scene graph and adds visible object to the render queue.
Then, after setting up the render system (e.g. matrices, lighting, etc), real rendering is started by calling SceneManager::_renderVisibleObjects().

SceneManager::renderSingleObject() is the real function that render a object. It setup the render states of the object. (e.g matrices, materials, shaders, vertex/index buffers)

Tuesday, June 5, 2007

Adding sort direction arrow into GridView

Call this function @ RowCreated event:
public static void AddSortingArrow(GridView gv, GridViewRowEventArgs e)
{
  if (e.Row.RowType != DataControlRowType.Header)
    return;
  foreach (TableCell tc in e.Row.Cells)
  {
    if (tc.HasControls())
    {
      LinkButton lnk = (LinkButton)tc.Controls[0];
      if (lnk != null)
      {
        Label lbl = new Label();
        lbl.Text = (gv.SortDirection == SortDirection.Ascending ? "▲" : "▼");
        if (gv.SortExpression == lnk.CommandArgument)
        {
            lbl.Text = " " + lbl.Text;
            tc.Controls.Add(lbl);
        }
      }
    }
  }
}

Wednesday, May 30, 2007

VC simple mem leak detection code

Add these lines into header:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
Call this function @ entry point
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );