📄 renderer.cpp
字号:
}
/////////////////////////////////////////////////////////////////////////////
//
// class Renderer camera and reference frame maintenance functions
//
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
// Renderer::setCamera
//
// Sets the position and orientation of the camera
void Renderer::setCamera(const Vector3 &pos, const EulerAngles &orient) {
// Remember position and orientation
cameraPos = pos;
cameraOrient = orient;
// Recompute world -> camera matrix
worldToCameraMatrix.setupParentToLocal(cameraPos, cameraOrient);
// Upload this to the rendering API, if we have been initted
if (pD3DDevice != NULL) {
// Convert our 4x3 matrix to D3D-style 4x4 matrix
D3DMATRIX m;
m._11 = worldToCameraMatrix.m11;
m._12 = worldToCameraMatrix.m12;
m._13 = worldToCameraMatrix.m13;
m._14 = 0.0f;
m._21 = worldToCameraMatrix.m21;
m._22 = worldToCameraMatrix.m22;
m._23 = worldToCameraMatrix.m23;
m._24 = 0.0f;
m._31 = worldToCameraMatrix.m31;
m._32 = worldToCameraMatrix.m32;
m._33 = worldToCameraMatrix.m33;
m._34 = 0.0f;
m._41 = worldToCameraMatrix.tx;
m._42 = worldToCameraMatrix.ty;
m._43 = worldToCameraMatrix.tz;
m._44 = 1.0f;
// Tell D3D about it
HRESULT result = pD3DDevice->SetTransform(D3DTS_VIEW, &m);
assert(SUCCEEDED(result));
}
// The model->clip matrix must be recomputed, next time we need it
needToComputeModelToClipMatrix = true;
}
//---------------------------------------------------------------------------
// Renderer::setZoom
//
// Sets the horizontal and vertical zoom factors. You may specify the two
// values manually, or you can specify only one value, and have the other
// value be automatically computed according to the porportions of the
// window. Pass 0.0 to mean "auto-compute this value." You must specify
// at least one zoom value - you can't "auto-compute" both values.
void Renderer::setZoom(float xZoom, float yZoom) {
// Remember zoom values
zoomX = xZoom;
zoomY = yZoom;
// Re-compute the clip matrix.
computeClipMatrix();
}
//---------------------------------------------------------------------------
// Renderer::setNearFarClippingPlanes
//
// Sets the near and far clippping plane distances. Setting the proper
// distance is important because it effects depth buffering resolution.
// Remember that the z-buffer only has limited precision. The near and
// far clipping planes are used to scale the depth values in order to
// maximize the resolution. You should set the far clipping plane
// to a reasonable maximum length, say twice the farthest thing you
// expect to draw in your scene. The near clipping plane is
// necessary to prevent divide by zero in the perspective division.
// A reasonable value might be 1 foot or 1 inch or so.
void Renderer::setNearFarClippingPlanes(float n, float f) {
// Sanity check
assert(n > 0.0f);
assert(f > n);
// Remember values
nearClipPlane = n;
farClipPlane = f;
// Re-compute the clip matrix.
computeClipMatrix();
}
//---------------------------------------------------------------------------
// Renderer::setNearFarClippingPlanes
//
// Sets the 2D output viewport window. Coordinates are in screen space
// (i.e. pixels.)
void Renderer::setWindow(int x1, int y1, int xSize, int ySize) {
// Sanity check.
assert(xSize > 0);
assert(ySize > 0);
// Remember window values
windowX1 = x1;
windowY1 = y1;
windowSizeX = xSize;
windowSizeY = ySize;
windowX2 = x1 + xSize;
windowY2 = y1 + ySize;
// Compute values for software projection
halfWindowSizeX = (float)windowSizeX / 2.0f;
halfWindowSizeY = (float)windowSizeY / 2.0f;
windowCenterX = (float)windowX1 + halfWindowSizeX;
windowCenterY = (float)windowY1 + halfWindowSizeY;
// Upload to the direct3D device, if we are ready
if (pD3DDevice != NULL) {
D3DVIEWPORT8 viewData;
viewData.X = x1;
viewData.Y = y1;
viewData.Width = xSize;
viewData.Height = ySize;
viewData.MinZ = 0.0F;
viewData.MaxZ = 1.0F;
HRESULT result = pD3DDevice->SetViewport(&viewData);
assert(SUCCEEDED(result));
}
// Since the window proportions may have changed, the clip
// matrix may need to change.
computeClipMatrix();
}
//---------------------------------------------------------------------------
// Renderer::setFullScreenWindow
//
// Sets the window to the full screen. This is really just shorthand
// for a very common operation.
void Renderer::setFullScreenWindow() {
setWindow(0, 0, screenX, screenY);
}
//---------------------------------------------------------------------------
// Renderer::getWindow
//
// Accessor to get the window dimensions
void Renderer::getWindow(int *x1, int *y1, int *xSize, int *ySize) {
// Return whatever options they request
if (x1 != NULL) *x1 = windowX1;
if (y1 != NULL) *y1 = windowY1;
if (xSize != NULL) *xSize = windowSizeX;
if (ySize != NULL) *ySize = windowSizeY;
}
//---------------------------------------------------------------------------
// Renderer::instance
//
// "Instance" a reference frame, nested within the current modeling space.
// This hails from OpenGL. See the comments at the top of this file
// regarding the nesting system and its purpose.
void Renderer::instance(const Vector3 &pos, const EulerAngles &orient) {
// Make sure we aren't full
assert(instanceStackPtr < kMaxInstanceDepth-1);
// Get shortcut to destination entry in the stack
++instanceStackPtr;
InstanceInfo *d = &instanceStack[instanceStackPtr];
// Check for a very special common case - the first level.
// We can avoid some matrix computations in this case.
if (instanceStackPtr == 1) {
// Compute model to world matrix directly. We
// assume that the parent->world matrix is identity
d->modelToWorldMatrix.setupLocalToParent(pos, orient);
} else {
// We are nested and must concatenate. First
// we compute the local->parent matrix
Matrix4x3 localToParent;
localToParent.setupLocalToParent(pos, orient);
// Concatenate with the parent->world matrix
d->modelToWorldMatrix = localToParent * instanceStack[instanceStackPtr-1].modelToWorldMatrix;
}
// Update world matrix to D3D
updateModelToWorldMatrix();
}
//---------------------------------------------------------------------------
// Renderer::instancePop
//
// "Pop" the instance stack one level - restoring the reference frame to the
// parent.
void Renderer::instancePop() {
// Make sure stack isn't empty
assert(instanceStackPtr > 0);
// Pop stack
--instanceStackPtr;
// Update world matrix to D3D
updateModelToWorldMatrix();
}
/////////////////////////////////////////////////////////////////////////////
//
// class Renderer render context functions
//
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
// Renderer::setDepthBufferMode
//
// Enable/disable reading and/or writing of the depth buffer.
//
// When depth buffering is disabled, pixels are written regardless of
// any previous values in the depth buffer.
//
// When depth writing is disabled, the depth buffer is not updated, even
// when a color value is written to the frame buffer.
//
// Default operation is for both reading and writing to be enabled
void Renderer::setDepthBufferMode(bool readEnabled, bool writeEnabled) {
// Check if read mode changing
if (depthBufferRead != readEnabled) {
depthBufferRead = readEnabled;
setD3DRenderState(D3DRS_ZFUNC, readEnabled ? D3DCMP_LESSEQUAL : D3DCMP_ALWAYS);
}
// Check if write mode changing
if (depthBufferWrite != writeEnabled) {
depthBufferWrite = writeEnabled;
setD3DRenderState(D3DRS_ZWRITEENABLE, writeEnabled);
}
}
//---------------------------------------------------------------------------
// Renderer::setBlendEnable
//
// Enable/disable alpha blending. Why would you want to do disable alpha
// blending?
//
// First, depending on the rendering hardware, it may be faster to render
// without alpha blending, even if you know that it would not make a visual
// difference.
//
// Second, you may wish to render with textures that contain alpha, or with
// alpha in the vertices, and you wish to ignore that alpha data.
void Renderer::setBlendEnable(bool blend) {
// Check if state changing
if (blendEnable != blend) {
// Remember new state
blendEnable = blend;
// Set state to D3D
setD3DRenderState(D3DRS_ALPHABLENDENABLE, blend);
}
}
//---------------------------------------------------------------------------
// Renderer::setSourceBlendMode
// Renderer::setDestBlendMode
//
// Set the source/dest blend factors to use when alpha blending. Remember,
// when a pixel is going to be written to the frame buffer, it's value is
// computed as:
//
// (sf*sc) + (df*dc)
//
// Where:
//
// sc is the "source" color. That is, the color of the pixel
// on the polygon after it has been lit and fogged.
// dc is the "destination" color. This is the color that is
// already in the frame buffer - the color that we are "blending
// on top of."
// sf/df are the source and destination blend factors, respectively.
// These values are actually ARGB colors, not simple scalars.
// However, they often are "greyscale values" based on the same
// scalar used in all channels. They can either be a constant,
// such as 0 or 1, or they may be computed per pixel based on
// a number of different factors. The most frequently used
// factor to use is the source alpha.
//
// A few examples of common source/dest combinations:
//
//
// eSourceBlendModeSrcAlpha, eDestBlendModeInvSrcAlpha
//
// "Normal" alpha blending, where the alpha channel basically
// controls the "opacity" of the source, and the final color is
// a simple linear interpolation between the source and destination
// colors.
//
//
// eSourceBlendModeSrcAlpha, eDestBlendModeOne
//
// "Additive" blending. The source color (times alpha) is added to the
// destination. This is useful for special effects like fires, halos,
// lens flares, explosions, etc. Alpha acts as a "brightness control"
//
//
// eSourceBlendModeZero, eDestBlendModeSrcColor
//
// "Multiplicative" blending. The source and destination colors are
// multiplied together to produce the final output color. Alpha is
// ignored. This is often used for multi-pass lightmapping, where
// one pass is the diffuse texture, and another texture controls
// lighting on a per-texel basis.
//
//
// We have not provided enums for all the possible blending modes
// supported by DirectX. We have done this for a couple or reasons.
// First, this engine is a learning engine. We have limited the options
// in order to simplify. Second, many of the options are not portable.
// Some graphics cards don't support all the combinations. (I.e. the
// PS2 cannot do multiplicative blending.) Third, many of the options
// aren't that useful for comon purposes. We have tried to provide
// the most useful modes, and omitted the more "advanced" or "esoteric"
// modes.
void Renderer::setSourceBlendMode(ESourceBlendMode mode) {
// Check if state changing
if (sourceBlendMode != mode) {
// Remember new state
sourceBlendMode = mode;
// Map our enum to D3D enum
D3DBLEND b;
switch (mode) {
default:
assert(false);
case eSourceBlendModeSrcAlpha:
b = D3DBLEND_SRCALPHA;
break;
case eSourceBlendModeOne:
b = D3DBLEND_ONE;
break;
case eSourceBlendModeZero:
b = D3DBLEND_ZERO;
break;
}
// Set state to D3D
setD3DRenderState(D3DRS_SRCBLEND, b);
}
}
void Renderer::setDestBlendMode(EDestBlendMode mode) {
// Check if state changing
if (destBlendMode != mode) {
// Remember new state
destBlendMode = mode;
// Map our enum to D3D enum
D3DBLEND b;
switch (mode) {
default:
assert(false);
case eDestBlendModeInvSrcAlpha:
b = D3DBLEND_INVSRCALPHA;
break;
case eDestBlendModeOne:
b = D3DBLEND_ONE;
break;
case eDestBlendModeZero:
b = D3DBLEND_ZERO;
break;
case eDestBlendModeSrcColor:
b = D3DBLEND_SRCCOLOR;
break;
}
// Set state to D3D
setD3DRenderState(D3DRS_DESTBLEND, b);
}
}
//---------------------------------------------------------------------------
// Renderer::setRGB
//
// Sets the global constant color, which is used for 2D primitives. We do
// not use constant color to shade 3D polygons. You must use prelit
// polygons for that, and put the color in the vertices.
//
// Any alpha int he input is ignored, and the global constant alpha is not
// unchanged.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -