⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renderer.cpp

📁 3D数学基础:图形与游戏开发书籍源码,里面有很多实用的代码,对做3D的同志很有意义
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

/////////////////////////////////////////////////////////////////////////////
//
// 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 + -