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

📄 renderer.cpp

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

				case D3DFMT_R8G8B8:
				case D3DFMT_X8R8G8B8:
					ourMode.bitsPerPixel = 24;
					break;

				case D3DFMT_R5G6B5:
				//case D3DFMT_X1R5G5B5:
				//case D3DFMT_A1R5G5B5:
				//case D3DFMT_A4R4G4B4:
				//case D3DFMT_X4R4G4B4:
					ourMode.bitsPerPixel = 16;
					break;

				default:

					// Unknown or unrecognized mode - skip it

					continue;
			}

			// Count it, or add it to the list

			if (pass == 0) {

				// 1st pass - just count it

				++videoModeCount;
			} else {

				// 2nd pass.  Actually add it to the list.
				// First, we check for duplicates

				bool	dup = false;
				for (int i = 0 ; i < videoModeCount ; ++i) {
					VideoMode *v = &videoModeList[i];
					if (
						(v->xRes == ourMode.xRes) &&
						(v->yRes == ourMode.yRes) &&
						(v->bitsPerPixel == ourMode.bitsPerPixel) &&
						(v->refreshHz == ourMode.refreshHz)
					) {
						dup = true;
						break;
					}
				}

				// Add it, if not a dup

				if (!dup) {
					videoModeList[videoModeCount] = ourMode;
					++videoModeCount;
				}
			}

			// Keep enumerating video modes
		}

		// Any valid modes found?

		if (videoModeCount == 0) {

			// Nope - clean up and report failure.

			pD3D->Release();
			pD3D = NULL;
			return 0;
		}

		// End of first pass?

		if (pass == 0) {

			// Yep.  Allocate list.  Notice that we are
			// possibly allocating more memory than we
			// will need, because there might be duplicates.
			// We don't care about minor differences in
			// pixel formats with the same bit depth

			videoModeList = new VideoMode[videoModeCount];

			// Reset count for next pass

			videoModeCount = 0;
		}
	}

	// Return number of modes

	return videoModeCount;
}

//---------------------------------------------------------------------------
// Renderer::getVideoMode
//
// Returns a video mode, by index

const VideoMode &Renderer::getVideoMode(int index) {

	// Make sure list is built

	if (getVideoModeCount() < 1) {
		ABORT("3D support not detected.");
	}
	assert(videoModeCount > 0);
	assert(pD3D != NULL);

	// Index should be in range

	assert(index >= 0);
	assert(index < videoModeCount);

	// Return it

	return videoModeList[index];
}

//---------------------------------------------------------------------------
// Renderer::init
//
// Startup the renderer in the specified screen mode.  This must be called
// only once, at program startup.  You MUST call this before any other
// 3D calls are made.

void	Renderer::init(const VideoMode &mode) {
	HRESULT	result;

	// Make sure Direct3D interface is created

	getVideoModeCount();

	// We should have a D3D object, but not a D3D object

	assert(pD3D != NULL);
	assert(pD3DDevice == NULL);

	// Figure out actual pixel format to use for desired bit depth

	int		modeIndex = 0;
	D3DDISPLAYMODE	d3dMode;
	for (;;) {

		// Get the mode

		result = pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT,modeIndex,&d3dMode);
		++modeIndex;

		// No more modes?  Then we couldn't find an appropriate mode

		if (FAILED(result)) {
			ABORT("Can't find valid video mode for %dx%dx%dbpp", mode.xRes, mode.yRes, mode.bitsPerPixel);
		}

		// Will this mode do for what they want?

		if (d3dMode.Width != mode.xRes) continue;
		if (d3dMode.Height != mode.yRes) continue;
		if (mode.bitsPerPixel == 16) {

			if (d3dMode.Format == D3DFMT_R5G6B5) {
				break;
			}

		} else if (mode.bitsPerPixel == 24) {

			if (d3dMode.Format == D3DFMT_R8G8B8) {
				break;
			}
			if (d3dMode.Format == D3DFMT_X8R8G8B8) {
				break;
			}

		} else if (mode.bitsPerPixel == 32) {

			if (d3dMode.Format == D3DFMT_A8R8G8B8) {
				break;
			}

		} else {

			// Huh?  You are asking for an invalid bit depth

			assert(false);
		}
	}

	// Figure out Z buffer format.  We'll start by assuming
	// a 16-bit depth buffer

	D3DFORMAT depthBufferFormat = D3DFMT_D16;

	// If in higher bit depth, we'll shoot for the depth buffer
	// with the most resolution possible

	if (mode.bitsPerPixel > 16) {

		// First, try a full 32-bit z-buffer.
		// if that doesn't work, we'll try a 24-bit
		// z-buffer

		if (SUCCEEDED(pD3D->CheckDeviceFormat(
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			d3dMode.Format,
			D3DUSAGE_DEPTHSTENCIL,
			D3DRTYPE_SURFACE,
			D3DFMT_D32
		))) {
			depthBufferFormat = D3DFMT_D32;
		} else if (SUCCEEDED(pD3D->CheckDeviceFormat(
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			d3dMode.Format,
			D3DUSAGE_DEPTHSTENCIL,
			D3DRTYPE_SURFACE,
			D3DFMT_D24S8
		))) {
			depthBufferFormat = D3DFMT_D24S8;
		}
	}

	// Fill in the "present" parameters

	D3DPRESENT_PARAMETERS	presentParms;
	presentParms.BackBufferWidth = mode.xRes;
	presentParms.BackBufferHeight = mode.yRes;
	presentParms.Windowed = 0;
	presentParms.BackBufferFormat = d3dMode.Format;
	presentParms.MultiSampleType = D3DMULTISAMPLE_NONE;
	presentParms.EnableAutoDepthStencil = TRUE;
	presentParms.AutoDepthStencilFormat = depthBufferFormat;
	presentParms.Flags = 0;
	presentParms.hDeviceWindow = gHwndApp;
	presentParms.BackBufferCount = 2;
	presentParms.SwapEffect = D3DSWAPEFFECT_FLIP;
	if (mode.refreshHz == kRefreshRateDefault) {
		presentParms.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	} else if (mode.refreshHz == kRefreshRateFastest) {
		presentParms.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
	} else {
		assert(mode.refreshHz > 0);
		presentParms.FullScreen_RefreshRateInHz = mode.refreshHz;
	}
	presentParms.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

	// Create hardware transform device, hopefully with vertex and
	// pixel shader support.

	result = pD3D->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		gHwndApp,
		D3DCREATE_FPU_PRESERVE | D3DCREATE_HARDWARE_VERTEXPROCESSING,
		&presentParms,
		&pD3DDevice
	);
	if (!SUCCEEDED(result)) {

		// Nope - try falling back on software vertex processing

		result = pD3D->CreateDevice(
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			gHwndApp,
			D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
			&presentParms,
			&pD3DDevice
		);
		if (!SUCCEEDED(result)) {
			ABORT("Can't set video mode to %dx%dx%dbpp", mode.xRes, mode.yRes, mode.bitsPerPixel);
		}
	}

	// Remember resolution

	screenX = mode.xRes;
	screenY = mode.yRes;

	// Set a full screen window initially

	setFullScreenWindow();

	// Clear out any garbage on the screen

	for (int i = 0 ; i < 4 ; ++i) {
		beginScene();
		clear(kClearFrameBuffer | kClearDepthBuffer);
		endScene();
		flipPages();
	}

	// Set a default render state

	setD3DRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
	setD3DRenderState(D3DRS_ZWRITEENABLE, TRUE);
	setD3DRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
	setD3DRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	setD3DRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	setD3DRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	setD3DRenderState(D3DRS_AMBIENT, ambientLightColor);
	setD3DRenderState(D3DRS_FOGENABLE, fogEnable);
	setD3DRenderState(D3DRS_FOGCOLOR, fogColor);
	setD3DRenderState(D3DRS_FOGSTART, *(DWORD*)(&fogNear));
	setD3DRenderState(D3DRS_FOGEND, *(DWORD*)(&fogFar));
	setD3DRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

	// Set texture wrapping mode

	result = pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
	assert(SUCCEEDED(result));
	result = pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
	assert(SUCCEEDED(result));

	// Setup the material with the properties that we want

	memset(&d3dMaterial, 0, sizeof(d3dMaterial));
	d3dMaterial.Diffuse.r = 1.0f;
	d3dMaterial.Diffuse.g = 1.0f;
	d3dMaterial.Diffuse.b = 1.0f;
	d3dMaterial.Diffuse.a = 1.0f;
	d3dMaterial.Ambient = d3dMaterial.Diffuse;
	d3dMaterial.Specular = d3dMaterial.Diffuse;
	d3dMaterial.Power = 50.0f; // arbitrary

	// Force upload of the D3D material

	constantARGB ^= 0xff000000; // force alpha portion to change
	setOpacity(constantOpacity);

	// Setup directional light

	memset(&d3dDirectionalLight, 0, sizeof(d3dDirectionalLight));
	d3dDirectionalLight.Type = D3DLIGHT_DIRECTIONAL;
	d3dDirectionalLight.Diffuse.r = GET_R(directionalLightColor) / 255.0f;
	d3dDirectionalLight.Diffuse.g = GET_G(directionalLightColor) / 255.0f;
	d3dDirectionalLight.Diffuse.b = GET_B(directionalLightColor) / 255.0f;
	d3dDirectionalLight.Diffuse.a = 0.0f;
	d3dDirectionalLight.Specular = d3dDirectionalLight.Diffuse;
	d3dDirectionalLight.Ambient.r = 0.0f;
	d3dDirectionalLight.Ambient.g = 0.0f;
	d3dDirectionalLight.Ambient.b = 0.0f;
	d3dDirectionalLight.Ambient.a = 0.0f;
	d3dDirectionalLight.Direction.x = directionalLightVector.x;
	d3dDirectionalLight.Direction.y = directionalLightVector.y;
	d3dDirectionalLight.Direction.z = directionalLightVector.z;
	d3dDirectionalLight.Falloff = 1.0f;
	d3dDirectionalLight.Theta = kPi;
	d3dDirectionalLight.Phi = kPi;
	setD3DDirectionalLight();

	// Enable it

	result = pD3DDevice->LightEnable(0, TRUE);
	assert(SUCCEEDED(result));

	// Prepare the texture cache

	resetTextureCache();
}

//---------------------------------------------------------------------------
// Renderer::shutdown
//
// Called to shutdown the renderer.  This MUST be called at program shutdown
// time, and no other renderer calls may be made after that

void	Renderer::shutdown() {

	// Free texture resources

	freeAllTextures();

	// Delete Direct3D device object

	if (pD3DDevice != NULL) {
		pD3DDevice->Release();
		pD3DDevice = NULL;
	}

	// Delete Direct3D interface

	if (pD3D != NULL) {
		pD3D->Release();
		pD3D = NULL;
	}

	// Delete list of video modes

	delete [] videoModeList;
	videoModeList = NULL;
	videoModeCount = 0;
}

//---------------------------------------------------------------------------
// Renderer::flipPages
//
// Called when scene rendering is complete, to "present" the back buffer

void	Renderer::flipPages() {

	// Make sure we have a device

	if (pD3DDevice != NULL) {

		// Toggle it

		HRESULT result = pD3DDevice->Present(NULL,NULL,NULL,NULL);

		// We could lose the surface - we'll ignore this error

		assert((result == D3DERR_DEVICELOST) || SUCCEEDED(result));
	}

	// Perform frame-time processing

	idle();
}

//---------------------------------------------------------------------------
// Renderer::beginScene
//
// Called at the beginning of the scene.  You must call this before any
// rendering primitives.

void	Renderer::beginScene() {

	// Make sure we have a device

	if (pD3DDevice == NULL) {
		assert(false);
	} else {

		// Do it

		HRESULT result = pD3DDevice->BeginScene();
		assert(SUCCEEDED(result));
	}
}

//---------------------------------------------------------------------------
// Renderer::endScene
//
// Called at the end of the scene.  You must call this after all
// primitives have been rendered.

void	Renderer::endScene() {

	// Make sure we have a device

	if (pD3DDevice == NULL) {
		assert(false);
	} else {

		// Do it

		HRESULT result = pD3DDevice->EndScene();
		assert(SUCCEEDED(result));
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -