📄 renderer.cpp
字号:
void Renderer::setRGB(unsigned int rgb) {
// Mask off alpha value in the input color, if any alpha
// was specified.
rgb &= 0x00ffffff;
// Set RGB portion, leaving alpha portion unchanged
constantARGB = (constantARGB & 0xff000000) | rgb;
}
//---------------------------------------------------------------------------
// Renderer::setARGB
//
// Sets the global constant color and opacity simulataneously
void Renderer::setARGB(unsigned argb) {
// Set const alpha value using floating point function
setOpacity(GET_A(argb) / 255.0f);
// Slam value
constantARGB = argb;
}
//---------------------------------------------------------------------------
// Renderer::setOpacity
//
// Sets the global constant alpha value. This is used for 2D primitives,
// and for 3D primitives than do not specify a color in the vertex. For any 3D
// primitives that specify a color in the vertex (such as those using
// RenderVertexL) the alpha comes directly from the vertex.
void Renderer::setOpacity(float a) {
// Sanity check range
assert(a >= 0.0f);
assert(a <= 1.0f);
// Snap to nearest value of 255
int newAlpha = (int)floor(a * 255.0f + .5f);
// Check if value not changing
if (newAlpha == GET_A(constantARGB)) {
return;
}
// Remember value in floating point and in the
// alpha bits of the global constant color
constantOpacity = (float)newAlpha / 255.0f;
constantARGB = (newAlpha << 24) | (constantARGB & 0x00ffffff);
// Set the alpha values in the D3D Material
d3dMaterial.Diffuse.a = constantOpacity;
d3dMaterial.Ambient.a = constantOpacity;
d3dMaterial.Specular.a = constantOpacity;
// Tell D3D
if (pD3DDevice == NULL) {
assert(false);
return;
}
HRESULT result = pD3DDevice->SetMaterial(&d3dMaterial);
assert(SUCCEEDED(result));
}
//---------------------------------------------------------------------------
// Renderer::setFogEnable
//
// Enable of disable fog.
void Renderer::setFogEnable(bool flag) {
// Check if state changing
if (fogEnable != flag) {
// Remember new state
fogEnable = flag;
// Set state to D3D
setD3DRenderState(D3DRS_FOGENABLE, flag);
}
}
//---------------------------------------------------------------------------
// Renderer::setFogColor
//
// Sets the fog color. That is, the color that objects fade towards as they
// are fogged out.
void Renderer::setFogColor(unsigned rgb) {
// Mask off alpha value in the input color, if any alpha
// was specified.
rgb &= 0x00ffffff;
// Check if state changing
if (fogColor != rgb) {
// Remember new state
fogColor = rgb;
// Set state to D3D
setD3DRenderState(D3DRS_FOGCOLOR, rgb);
}
}
//---------------------------------------------------------------------------
// Renderer::setFogDistance
//
// Sets the fog distances:
//
// nearFog The distance where the fog effect starts. Objects
// within this distance receive no fog effect.
// farFog The distance where objects are completely fogged
// out.
void Renderer::setFogDistance(float nearFog, float farFog) {
// Check if near value changing
if (nearFog != fogNear) {
// Yes - remember new value
fogNear = nearFog;
// Update to D3D
setD3DRenderState(D3DRS_FOGSTART, *(DWORD*)(&nearFog));
}
// Check if far value changing
if (farFog != fogFar) {
// Yes - remember new value
fogFar = farFog;
// Update to D3D
setD3DRenderState(D3DRS_FOGEND, *(DWORD*)(&farFog));
// Re-compute the clip matrix. We pre-compute
// the far value in clip coordinates for outcode
// testing. This value is computed in this function.
computeClipMatrix();
}
}
//---------------------------------------------------------------------------
// Renderer::setAmbientLightColor
//
// Sets the ambient light color. When lighting is enabled, this is the
// light color that is always present, even when no other light is
// shining on the object.
//
// Usually, it is a relatively dark greyscale value, such as (64,64,64)
//
// See Section 15.4 for more on lighting.
void Renderer::setAmbientLightColor(unsigned rgb) {
// Mask off alpha value in the input color, if any alpha
// was specified.
rgb &= 0x00ffffff;
// Check if state changing
if (ambientLightColor != rgb) {
// Remember new state
ambientLightColor = rgb;
// Set state to D3D
setD3DRenderState(D3DRS_AMBIENT, rgb);
}
}
//---------------------------------------------------------------------------
// Renderer::setDirectionalLightVector
//
// Controls the direction of the directional light. The input vector
// is a unit vector in inertial space which points in the direction that
// the light is "facing." In other words, it points away from the light,
// not towards the light. (This is the opposite of the l vector.) E.g.
// at high noon, you could use (0, -1, 0) for the sun.
//
// See Section 15.4 for more on lighting.
void Renderer::setDirectionalLightVector(const Vector3 &v) {
// Sanity check - the input vector should be normalized
assert(fabs(vectorMag(v) - 1.0f) < .001f);
// Check if state changing
if (directionalLightVector != v) {
// Remember new state
directionalLightVector = v;
// Set light vector in D3D light struct
d3dDirectionalLight.Direction.x = directionalLightVector.x;
d3dDirectionalLight.Direction.y = directionalLightVector.y;
d3dDirectionalLight.Direction.z = directionalLightVector.z;
// Set it to D3D
setD3DDirectionalLight();
}
}
//---------------------------------------------------------------------------
// Renderer::setDirectionalLightColor
//
// Controls the color of the directional light.
//
// See Section 15.4 for more on lighting.
void Renderer::setDirectionalLightColor(unsigned rgb) {
// Mask off alpha value in the input color, if any alpha
// was specified.
rgb &= 0x00ffffff;
// Check if state changing
if (directionalLightColor != rgb) {
// Remember new state
directionalLightColor = rgb;
// Put color into diffuse and specular channels of
// D3D light struct
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.Specular = d3dDirectionalLight.Diffuse;
// Set it to D3D
setD3DDirectionalLight();
}
}
//---------------------------------------------------------------------------
// Renderer::setLightEnable
//
// Enable/disable lighting calculations for 3D primitives that do not
// specify a color explicitly. (i.e. primitives using RenderVertex vertices.)
// This has no effect on 2D primitives or prelit primites.
//
// When lighting is enabled, the current lighting context (ambient light,
// directional light vector, etc.) is used in conjunction with the
// vertex normal to compute a lighting value.
//
// When lighting is disabled, the primitive is drawn "unlit" - i.e. fully
// bright, as if the result of the lighting equation was a white color.
//
// In either case, the opacity comes from the global constant opacity.
void Renderer::setLightEnable(bool flag) {
// Remember new state
lightEnable = flag;
// Note: we not apply this state directly to D3D.
// For some reason, D3D allows you to "enable" lighting,
// even if your vertices are already prelit and don't
// have a normal. Sort of stupid. So we must manually
// control the lighting flag on a per-primitive basis
}
//---------------------------------------------------------------------------
// Renderer::setBackfaceMode
//
// Controls culling of primitives based on clockwise/counterclockwise
// enumeration of vertices in screen space.
//
// eBackfaceModeCCW Polygons with vertices enumerated counter-clockwise
// are culled. This is the default, since we normally
// list our vertices clockwise around the polygon.
//
// eBackfaceModeCW Polygons with vertices enumerated clockwise are
// culled. This can be useful if we have "mirrored"
// an object, or the view, since the faces are flipped
// inside out.
//
// eBackfaceModeDisable No polygons are culled based on vertex order.
void Renderer::setBackfaceMode(EBackfaceMode mode) {
// Check if state changing
if (backfaceMode != mode) {
// Remember new state
backfaceMode = mode;
// Map our enum to D3D enum
D3DCULL c;
switch (mode) {
default:
assert(false);
case eBackfaceModeCCW:
c = D3DCULL_CCW;
break;
case eBackfaceModeCW:
c = D3DCULL_CW;
break;
case eBackfaceModeDisable:
c = D3DCULL_NONE;
break;
}
// Set state to D3D
setD3DRenderState(D3DRS_CULLMODE, c);
}
}
//---------------------------------------------------------------------------
// Renderer::selectTexture
//
// Select a texture into the rendering context. The texture is selected
// by handle
void Renderer::selectTexture(int handle) {
// Sanity check handle validity
if (handle < 1 || handle >= nextTextureSlot) {
assert(false);
return;
}
// Check if state is changing
if (handle != currentTextureHandle) {
// Get shortcut to structure
TextureCacheEntry *t = &textureCacheList[handle];
// Make sure texture exists
if (t->d3dTexture == NULL) {
assert(false);
return;
}
// Remember new state
currentTextureHandle = handle;
// Select it in D3D
assert(pD3DDevice != NULL);
HRESULT result = pD3DDevice->SetTexture(0, t->d3dTexture);
assert(SUCCEEDED(result));
}
}
//---------------------------------------------------------------------------
// Renderer::selectTexture
//
// Select a texture into the rendering context using a TextureReference.
// This interface can be more conveinent to use in the very common
// case where the texture is in a file - your upper level code doesn't
// have to keep track of the filename and the handle seperately -
// they are stored together.
//
// This function can be called on a texture that is not yet cached.
// in this case, the texture is "demand cached." However, for best
// performance, you should always cache all textures for before rendering
void Renderer::selectTexture(TextureReference &texture) {
// First, make sure the texture is cached in the graphics system,
// and the handle is correct. Notice that if the texture is
// already cached, then this should return very quickly.
cacheTexture(texture);
// Now, the handle is correct, and we can select the texture by
// handle.
selectTexture(texture.handle);
}
//---------------------------------------------------------------------------
// Renderer::setTextureClamp
//
// Enable/disbale texture clamping. When textures are clamped, UV values
// outside the 0...1 range are clamped, effectively "streaking" the outer
// pixel borders outward. When textures are not clamp, they are "tiled,"
// using only the fractional portion of the UV coordinates and discarding
// the numbers to the left of the decimal point.
void Renderer::setTextureClamp(bool flag) {
HRESULT result;
// Safety check - make sure we have a device
if (pD3DDevice == NULL) {
assert(false);
return;
}
// Check if state changing
if (textureClamp != flag) {
// Remember new state
textureClamp = flag;
// Figure out D3D addressing mode to use
D3DTEXTUREADDRESS m = flag ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
// Set state to D3D for both U and V
result = pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, m);
assert(SUCCEEDED(result));
result = pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, m);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -