THG
  • Аудио и видео
  • Бизнес и рынок
  • Видеокарты
  • Домашний компьютер
  • Игры и индустрия
  • Конкурсы
  • Накопители
  • Образование
  • Периферия
  • Платформы
  • Проекторы и мониторы
  • Процессоры
  • Сети и WiFi
  • Смартфоны и ноутбуки
  • Собери сам
  • Софт и утилиты
  • Фото
  • Обзоры
    • Смартфоны и ноутбуки
    • Аудио и видео
    • Проекторы и мониторы
    • Процессоры
    • Бизнес и рынок
    • Видеокарты
    • Домашний компьютер
    • Игры и индустрия
    • Конкурсы
    • Накопители
    • Периферия
    • Платформы
    • Техника для дома и сада
    • Сети и WiFi
    • Собери сам
    • Софт и утилиты
    • Фото
  • Статьи
  • Подборки
  • Новости
  • Форум
  • Контакты
  • Главная
THG
THG
  • Обзоры
    • Смартфоны и ноутбуки
    • Аудио и видео
    • Проекторы и мониторы
    • Процессоры
    • Бизнес и рынок
    • Видеокарты
    • Домашний компьютер
    • Игры и индустрия
    • Конкурсы
    • Накопители
    • Периферия
    • Платформы
    • Техника для дома и сада
    • Сети и WiFi
    • Собери сам
    • Софт и утилиты
    • Фото
  • Статьи
  • Подборки
  • Новости
  • Форум
  • Контакты
  • Главная
  • Видеокарты

Vertex Shaders and Pixel Shaders — THG.RU

  • 16.01.2002
0a51b3dc9a9389acd04eb326a05083cc
0a51b3dc9a9389acd04eb326a05083cc







Introduction

It was nearly a year ago that Microsoft released their latest version of DirectX. At the time, they said that the changes they’d made to the architecture were probably the biggest since DX5. Like a lot of people, I just assumed that this was typical marketing talk, but as it turns out, the new architectures introduced in DX8 have substantially changed the way that programmers should work with the graphics hardware available to them.

In this article I’ll discuss the pros and cons of the shader architecture for developers, and give you my opinions about the way games programmers are going to have to change to accommodate this new architecture.

Some of the discussion is going to be a little dry as architecture very often is, so I’ll warn you now that this article is going to be split into a few sections. For the real beginners to this topic, I’ll go through a brief introduction to the overall graphic pipeline, and what each element does. The next section will talk about some of the specific differences between the shader architecture introduced in DX8 and the traditional approaches available in DX7. Finally, I’ll discuss some of the changes that are going to be needed so that graphics engines can take advantage of these new technologies, along with some examples of their typical usage.

The Graphics Pipeline

The use of graphics engines in games is still a relatively young field. Only ten years ago the cutting-edge graphics engines were written as a hodgepodge of quick hacks and assembler inner loops. Only since the advent of graphics cards (and API’s that try to take advantage of them) have people started to look at ways of breaking down the rendering process into a set of logical blocks. At the moment, the graphics engine can be described simply as three different processing blocks:

Graphics Pipeline

The typical processing blocks of a graphics pipeline.

Primitive Processing

Primitive processing is a simple way to describe what the majority of a 3D game engine does. In one sentence: it takes game-specific data and data structures and produces vertices for the vertex processor to process.

Typically, these vertices will describe triangles, although it’s also possible that they will describe lines, points or point sprites (DX8). Currently, the game engine carries out the majority of the primitive processing, but in the future you can expect at least some primitive processing to be carried into the API domain.

With DirectX 8, some primitive processing has been introduced to the API, notably higher-order primitives, but so far there has been limited uptake from game developers. This could possibly be due to the fairly limited implementations available with DX8, but more likely it’s because there is little hardware out there currently that accelerates this functionality. ATI’s new series of cards promise to open up higher-order primitives to the games programmer under the name of «truform,» but Nvidia seems unimpressed, so for now, the jury’s out.

One thing is for certain, in the future you can be sure that this area of the API is going to increase in size and importance. Displacement maps, anybody?

Vertex Processing

Vertex processing can be further subdivided into a few major blocks of processing: notably, transformation, lighting, and to a limited extent, texture coordinate transformation.

Transformation involves taking position data as it’s stored in a vertex structure and transforming it into a ‘screenspace’ position. ‘Screenspace’ refers to the 2D plane that represents the viewer’s window onto the world. If you like, it’s the front of the monitor in the real world, and the viewer’s position in the game world. For traditional vertex processing, the transformation block does one of two things: it either passes the position data from the untransformed vertex to the transformed vertex without doing anything to it, or it passes the vertices through a world transform (matrix), followed by a view matrix, and finally a projection matrix.

Lighting has become an increasingly important part of the vertex processing step. As polygon density increases in game engines, it becomes more and more viable to carry out lighting as a vertex processing step. Traditionally, the most impressive lighting comes from static lighting calculated as a pre-process and stored as a texture (lightmaps). As polygon counts increase, dynamic lighting is starting to be carried out per-vertex. In the future, dynamic lighting will increasingly move into the pixel processing layer, although the vertex processor will still need to prepare data for the pixel processor.

Texture transformation involves passing the texture coordinates within the vertex formats to the pixel rasterization block. Most of the time, this block of processing does no more than pass through the texture coordinates. However, for animated textures, it’s possible to apply a matrix transform to the texture coordinates, enabling texture animation to be carried out without modifying the vertices (which would require the vertices to be modified in the VB, and subsequently re-uploaded across the AGP bus, an expensive operation nowadays). The texture transformation block can also be used to calculate texture coordinates for spherical and cubic reflection mapping.

Pixel Rasteriser

The final part of the pipeline takes data from the vertex processing step and puts it into the frame buffer as pixel values. Placing triangles on the frame buffer isn’t quite as easy as I’m making it sound. Before reaching the pixel rasterizer, the triangles are usually converted into scan lines, then the pixels in the scan line are passed through the rasterizer, one at a time. Actually, modern hardware often has a number of pixel rasterization blocks that will write more than one pixel at a time; however, this is transparent to the API user, so there’s no real need to worry about it.

The pixel rasterizer will take all of the information passed through from the vertex processor and compute a final pixel color, based on these values. A basic example of its usage might be to take the diffuse color and multiply it with the texture color (using the texture coordinates to retrieve a color from the current texture). A more complicated method might also add on a color from a reflection texture, using a second set of texture coordinates.

Differences Between DX7 and DX8 Pipelines

For this part of the article, I’ll introduce a few pieces of terminology to make my life simpler, and I’ll tell you what they are, to make your life simpler. The DX7 pipeline is commonly called the fixed-function pipeline, and from now on, I’ll just call it the FF pipeline. The DX8 pipeline introduces shader architecture in the guise of vertex shaders and pixel shaders, so from now on I’ll just call the DX8 pipeline the shader pipeline.

FF Vertex Processing

The FF pipeline is an extension of a very rigid system of vertex processing. The original vertex transformation pipeline can be traced right back to DX3, when there were only three types of vertices that you could use: the untransformed, unlit vertex; the untransformed and lit vertex; and, the transformed and lit vertex. From this basic structure the flexible vertex formats appeared, which now form the basics of the fixed-function pipeline in DX8. Flexible vertex formats allow you to set up vertices with a few basic properties defined. The following diagram shows an oversimplified version of the fixed-function vertex processor.

Vertex Processor

The fixed function vertex processor.

These pretty much correspond to the main types of processing as described in the introduction to vertex processing. The simplification of the diagram occurs from skimming over fixed-function support for matrix palette skinning and vertex blending, but these are basically additions to the transformation pipeline.

Vertex Shader Processing

In DX8, the vertex pipeline has been made entirely programmable. Arbitrary vertex data is processed in an arbitrary way using the vertex shader, which then places the output values into the write-only output registers.

Vertex Processor

The shader vertex processor.

As you can see, this diagram is considerably cleaner than the diagram for the fixed-function vertex pipeline, and, as a basic flow diagram, there’s little missing.

oPos is the ‘screenspace’ position of the vertex, oD0 is the diffuse color, oD1 is the specular color, oT0 up to oT3 are four pairs of texture coordinates. oFog is the range of the fog, allowing for a certain amount of flexibility, but not as much as some people would have wanted. oPts is the point size for the point sprite processor. Don’t worry about that one, point sprite processing is one of those things for the effects programmer to worry about.

FF Pixel Processing

The fixed-function pixel processing pipeline is, frankly, a bit of a mess. Commonly referred to as the texture cascade, once you start to look into how it works, you realize that this bit of architecture has probably outlived its usefulness.

The basic model is fairly simple to grasp. Each stage in the cascade computes a color and an alpha value, and passes these on to the next stage in the cascade. Once all of the stages have been computed, the pixel value is then passed to the frame buffer blending unit. Each stage has a color operation, typically with 2 arguments (although two triadic operations have been added for DX8), and an alpha operation, which is effectively another color operation that operates with scalar values.

The first weird and wonderful thing is that not all of these operations are supported on all hardware, so for each type of operation you want to use, you have to check that the hardware can support it. Most of this information can be extracted from the capabilities of the graphics card, however, more complicated issues are no longer handled by capabilities. For example, a certain cascade may work fine for 2D textures, but the processing will not work if the texture is a cube map.

To resolve these awkward compatibility cases, a function called ‘ValidateDevice’ was added to the API. Using this method, you set up the type of drawing you’d like to carry out, and then call ‘ValidateDevice.’ If the call fails, then you set up a simpler method and try again.

Unfortunately, ‘ValidateDevice’ is a fairly new thing, so older drivers will try to emulate ‘ValidateDdevice’s’ functionality, generally extremely poorly. So as well as ‘ValidateDevice,’ you’ll also want to check the capabilities of the graphics card. But, be aware that some old drivers will lie about their capabilities as well.

Hopefully that’s confused you, because it confuses everybody else. To summarize, something had to be done.

Pixel Shader Pipeline

The programmable pixel pipeline introduces a brand new pixel rasterization concept to DirectX along the lines of vertex shaders. They even have the same kind of name… pixel shaders.

There are a number of reasons that pixel shaders should rock the world, primarily related to the overcomplicated compatibility-checking necessary for the fixed-function pipeline. In pixel shaders, Microsoft has introduced an all-or-nothing style of compatibility. If a graphics card supports pixel shader (PS) 1.0, then you can guarantee that the graphics card supports all of the instructions available in PS1.0, as well as a fixed number of registers for texture coordinates, temporary variables, constants and vertex interpolated values.

The hassle of compatibility should become a thing of the past, leaving the hardware developers as the only people suffering from a sore head.

What Do Shaders Let Me Do?

In this section, I’ll describe a few of the typical things that you’ll want to use vertex and/or pixel shaders for when writing a game.

Matrix Palette Skinning

Matrix Palette Skinning

Matrix palette skinning.

«Skinning» is something that should be familiar to most people involved with character animation in modern games. You may remember the days when characters had a split halfway up the leg as they ran along. Some clever folks figured out a couple of ways to reduce the presence of those splits. Initially they found that you can add some extra polygons across the split in the geometry; later, people realized that you could bend a single cylinder in order to give a continuous piece of geometry. Nowadays, skinning allows you to use the cylinder trick, in a far more general way.

What the cylinder trick basically does is move the vertices along the cylinder, from one orientation to another. Skinning allows each vertex to be affected by up to four different orientations. Each of these orientations is described using a matrix. Generally, each matrix will be associated with a «bone» in the animation «skeleton» for the model.

A number of bones may be needed for a model; for a simple skeleton, we may have two feet, two lower legs, two upper legs, lower torso, upper torso, neck, two upper arms, two lower arms and two hands. That’s a total of 15 different bones. For more detailed models, you may want bones for multiple ribs in the upper torso, perhaps each finger, and maybe even each bone in the finger. In that case, you can easily reach 50-100 bones.

As I’ve already mentioned, each vertex will be affected by 4 different bones from the matrix palette. This means that each vertex will need to store an array of four indices per vertex, along with three blending weights (and an implied fourth blending value).

In DX8, there are two ways to carry out matrix palette skinning. First, an addition has been made to the fixed-function pipeline so that it can carry out matrix palette skinning using a 256 matrix palette. Second we can use the vertex shader layer to calculate skinning.

Each method has some drawbacks. The vertex shader method is limited to using the vertex shader constant memory, which only contains enough space for 24 matrices, and some of that memory is going to be used by a transformation matrix (-1 matrix), lighting data (at least -1 matrix), and data for whatever material model you use.

The fixed-function skinning routines are only currently accelerated on more recent MATROX graphics card and have no support from nVidia and ATI. But, then again, only the GF3 and R8500 support vertex shaders. So, you might think that it would be a good idea to use these fixed-function methods on older hardware. However, in profiling you’ll generally find that the fixed-function palette skinning is actually slower than vertex shader emulation.

In general, it’s going to be far more sensible to use the vertex shader method. So, for anything more complicated than the most basic skeletons, you’ll need to split the model up into zones, which reference no more than 20 matrices.

Bump-Reflection Mapping

Bump-Reflection Mapping

Bump-reflection-mapping.

This is a fairly standard use of the pixel shader architecture. Using the fixed-function pipeline, it’s possible to render bumpy surfaces using a variety of methods. The most powerful method is the DP3 instruction available on most modern hardware. The pixel shaders introduce a way to use data from one texture to read values from a different texture.

In the case of bump-reflection mapping, you can use the bump texture to modify your reads into a reflection map. In simple language, you have a bumpy, reflective surface.

The ability to read one texture using another is one of the main advances made by the pixel shader architecture, and is commonly referred to as a «dependent texture read». The implementation, as it exists in the first generation of pixel shaders, isn’t quite as powerful as it initially seems, mainly due to the rigid way that it must be used. All dependent texture reads occur in the first block of instructions in the pixel shader, and can only access data from the texture coordinates and textures passed in from the vertex shader. Once your texture reads are complete, they can be blended together using blend instructions.

For bump-reflection mapping, an orientation matrix must be passed into the pixel shader using the vertex shader’s texture coordinate output registers. This matrix requires three sets of texture coordinates. The remaining set of texture coordinates will be used to reference the bump-map. The result is that bump-reflection mapping takes an entire pass of rendering. If you also want to render a diffuse texture, you’ll have to do that in the first pass, then render the reflection on the second pass.

This is definitely a step up from the fixed-function pipeline, where this effect is impossible, but it is a fairly complicated process.

Making The Most Of The Vertex Shader Architecture Within A Game

Making The Most Of The Vertex Shader Architecture Within A Game

A variety of material models.

To demonstrate the limitations of vertex shaders, I’ll start with the idea that we want to write a graphics engine which can take full advantage of the vertex shader architecture. Rather than just using vertex shaders for a few special effects, I’ll show you some methods that allow us to use vertex shaders exclusively.

There are a number of reasons that we shouldn’t try to do this with PC game engines, I’ll go through these at the end of the section when you’ll be better able to understand them.

To begin with, we need to classify all of the geometry processing that we may wish to perform using the vertex shader architecture. The main classes of geometry processing are: the type of transformation we wish to apply to the vertex data; the lighting environment used for the vertices; and, the material models we will use to render the surfaces.

Materials are an interesting aspect of modern game engines. While it’s possible to maintain a relatively simple material model, in order to achieve the most impressive effects, far more complex material models are needed. For example, Dot3 bump-mapping requires that the lighting calculations are partially moved from the vertex processor into the pixel rasterizer. Although bump-mapping is mainly classed as a material property, it also means that the lighting block of the vertex processor is no longer used.

In fact, another common form of lighting requires that the lighting block carries out no processing whatsoever. «Static lighting,» using light maps, places all of the lighting information for the world into textures. These textures are then used to modulate the diffuse color of surfaces. The advantage of this type of lighting is that you can achieve very complex lighting effects that require days of processing before a level can be viewed in the engine. Unfortunately, it is too expensive to modify the light maps at runtime, so if dynamic lighting is needed, it must be added to the system using per-vertex processing, much as before.

The vertex lighting that we carry out in a vertex shader will typically consist of up to four lights, of type «positional,» «directional» or «spotlight.» Spotlights are less useful for vertex processing because vertex spotlights don’t give the soft edges that people want to see with complex lighting effects. However, there are still cases where you may wish to use relatively diffuse, uni-directional lights.

All the combinations of lighting, materials and vertex processing can result in a very large number of vertex shaders.

A lighting engine that allows up to four lights (which can be either directional, positional, or spotlights) leads to 34 different lighting environments. There are also a few different types of vertex position processing — skinned vertices, transformed vertices and untransformed vertices, which give us three different combinations of transformation. We’ll also have a number of different materials — probably between ten and one hundred different models for modern game engines. For argument’s sake, we’ll say we have twenty materials.

This means that we need to program a grand total of 2040 different vertex shaders if we want to be able to process every combination of vertex type, light state and material model.

Obviously very few companies will have the resources to hand-code this number of vertex shaders, so we need to find a way to reduce the amount of vertex shader code we need. The two ways of doing this are to either limit the number of combinations to a manageable number using a variety of techniques, or to provide a fully comprehensive, «fragment»-based vertex processing engine to handle automatic generation of each combination. I’ll go through these two approaches next.

Constrained Vertex Processing

Constrained vertex processing is by far the simplest way to solve the combinatorial explosion of vertex shaders. All it really involves is constraining our system until we can manage hand-coding the vertex shaders we need.

First, we need to look at lighting. To prevent needing to write too enormous a number of shaders, we need to get the number of lighting environments with standard vertex lighting from about 34 down to one, or at most two, within the lighting architecture. There are two extremes to the simplification. We can limit all of the geometry in the world to a single light; this guarantees the minimal amount of processing, but will have serious visual side effects, as objects move from one light to another. Or, at the other end of the spectrum, we can use four lights for every object; this will remove visual glitches when moving between small numbers of lights, but may involve a lot of wasted calculation for the majority of vertices.

The type of light we wish to use will also have an effect. Although directional and positional lights can both be simulated with a spotlight, it is probably more sensible to forget about spotlights for the time being. Directional lights will allow us to give a fair approximation of positional lights, although as the positional light moves closer to an object, the approximation will become worse. Positional lights allow us to give a good approximation of a directional light by placing the positional light a large distance from the object. Unfortunately, positional lights require one more instruction than directional lights for the simple no-attenuation case, and considerably more processing if we require attenuation.

There’s no reason that we have to use one or the other — in fact, we might decide to process two positional lights and two directional lights. In this case, we’ll be able to approximate most lighting environments relatively accurately, while incurring fewer penalties than if we were just using positional lights. If spotlights are needed, they could actually be used instead of one of the positional lights, giving us two directional, one positional and one spotlight, but most games won’t require spotlights. Basically, this decision has to be made on a case by case basis.

Now that we’ve reduced the number of lighting models down to one, we only have to worry about the combinations of vertex transformation and material systems. If we’re lucky, we’ll find that we only really need a large number of materials for one type of vertex transformation, probably the standard untransformed vertex. For skinned vertices and transformed vertices, we can limit the materials to one standard material type. Things won’t be quite as pretty, but we’ve no real option if we want to constrain the number of shaders.

Hopefully, once we’ve added these constraints to the system, we’ll have lowered our number of vertex shaders down to a manageable number. However, we’ve either sacrificed visual quality or processing time with the lighting and we’ve severely constrained our material model to only one form of vertex processing, all this to simply emulate what we could already do in the fixed-function pipeline. Of course, we can now add some funky special effects such as Blinn, or weird vertex transformations, and we’ve also limited the amount of time we’ll need to spend developing our vertex shader architecture.

Fragment Vertex Processing

Fragment processing is an idea that’s come to the foreground since DX8 was released to game developers. Appreciating that the number of possible shaders can get ridiculously large, nVidia have introduced the NVLink tool, which allows us to build shaders dynamically, from a set of «fragments.»

This approach has a number of good sides, and a fair number of bad sides, too. To start with, we need to define the fragment architecture that we wish to place over the top of the vertex shader architecture. Seeing as the main thing we want to do with this architecture is to emulate elements of the fixed-function pipeline, it’s probably best to start with something resembling that architecture.

Fragment based vertex processor

A simple fragment based vertex processor.

For a typical game engine, it’s easy to see where we’ll want to carry out each type of vertex processing. Our split between skinned vertices, untransformed vertices and transformed vertices occurs within the transformation block of the fragment processor.

Different lighting models are catered for by the lighting block, although there may be some interaction with the material block if we are using bump-mapping, which will typically take over the processing of light data, and effectively switch per-vertex lighting off.

The texture and material block takes care of various material models. The values it can affect are the diffuse, specular registers (for bump-mapping), and the texture coordinate output registers.

The lighting block of the pipeline will want to have access to the position and normal of the vertex. To maintain flexibility, it may be necessary for the texture and material pipeline to know about the position and normal of a vertex (useful for various effects), so our final block is called projection, and moves our world space position from a temporary register where it can be accessed by the material and lighting blocks, through a projective transform, and into the output register (which is write-only).

For each fragment to work together, the programmers using the system will have to adopt some basic programming conventions. Each fragment will need to know where the data from previous fragments has been placed. This can be done by stating that certain temporary registers will contain certain vertex data, or by using identifiers and letting the linker resolve names to handle register renaming. The latter case is already supported in NVLink, although, for in-house systems, it will be easier to establish temporary register conventions.

The introduction of processing blocks also introduces the need for automated optimization of the vertex shaders. It’s easy to see that the transformation block might move the world space position into a temporary register, even though the texture and material block doesn’t need this data. The output position block then carries out a wasted move instruction. It would have been more sensible to place the position directly in the output register during the transformation fragment. Linkers can be made to spot this type of optimization, along with the more difficult case where a multiply and add instruction could be pulled into a single, mad instruction.

Once the necessary architecture for fragment processing is in place, there are a number of interesting avenues open to the game developer. The most powerful possibility is to allow global distortion effects to be added to all of the vertex shaders in the world. To do this, we can add a new fragment block after the transformation block to carry out arbitrary world space distortion. Then, when we want to add the effect to the world, we can insert the new fragment into all of the existing vertex shaders and re-link them. Now all of the geometry in the world can wave in the wind, or be distorted from the center of a shockwave using a cosine wave, or whatever you can imagine.

This level of involvement is probably overkill for most game engines, but it’s possible that the extra architecture will be necessary for graphics engines that are attempting to be at the «bleeding edge» of technology.

The Problems

As I mentioned already, there are good reasons to never use the constrained vertex processing system outlined above. The main one being that you’ve already got the fixed-function pipeline. For most types of vertex processing, this is perfectly sufficient. Admittedly, the game engine won’t be able to take advantage of the most complex types of material model, but where specific special effects are needed, it’s easy enough to write constrained vertex shaders to carry out that processing.

There’s another good reason not to use vertex shaders on more recent hardware. The Radeon and GeForce1/2 graphics cards can all accelerate the fixed-function pipeline in hardware. However, if you want to use vertex shaders on these cards, you’ll have to process the vertex shader in software. Some people will tell you that on fast CPU’s you might as well process vertices on the CPU anyway, because the graphics card itself is only running at ~200 Mhz. However, the graphics card is carrying out some very specific operations in a highly optimized way, and it’s unlikely that anything less than a 1Ghz processor is going to be able to keep up with it. Also, for games which make heavy use of the CPU, any work moved from the GPU to the CPU is going to slow the game down. Having said that, there’s no reason not to process complex vertex shaders on the CPU if they can’t be emulated in the fixed-function pipeline on this type of hardware.

There is good evidence that carrying out some complex processing in software, and then leaving the transformation and lighting to the hardware can be substantially quicker than carrying out everything on the CPU. But if you’ve already programmed an effect using a vertex shader it’s generally going to be easier to process that entirely on the CPU, rather than to cut the code up into a software processing portion that produces vertices for the fixed function processor on the graphics card.

The fragment-based processing system also suffers from these problems when running on older graphics cards. Even though it can perfectly emulate the fixed-function pipeline, it’s quicker to use a fixed-function setup for T&L cards. On top of this vertex shaders have some limits which can make life far more complicated for the fragment processor. First, you can only have no more than 128 instuctions in a vertex shader, if you exceed this number of instructions the vertex shader will just fail to run on the hardware. You’re also limited to 96 constants in the current versions of vertex shaders. Once again, if you exceed this number of constants your automatic system is probably going to fail when it tries to set the 97th constant.

Although it’s uncommon for these types of situations to occur, it’s still possible to hit these limits in relatively real-world situations. For example, different types of lights require a different number of instructions, so if you have a scene with four spotlights and a heavyweight material, it’s more than likely that you’ll hit the instruction limit for the vertex shader. You can imagine that these kinds of scenes might occur rarely, but you certainly don’t want someone to accidentally point a torch at a surface illuminated by two car headlights, and for the surface to suddenly disappear! There is another case which is far more likely to occur, and this involves skinning. The problem is, that skinning will take up as much of the constant memory as it can for animation matrices. This means that an increase in the number of lights will easily make us hit the constant memory limit.

Using the fixed-function pipeline, it’s far rarer for a certain type of vertex transformation to limit the type of lighting you can apply to geometry. Even if you exceed the number of lights that your hardware can process, the driver has to try to process these vertices, even if performance drops.

And that is the issue that is generally at the heart of the problems with vertex shaders. When you’re using a processor you don’t have to worry about the size of the level one cache. If you exceed that amount of data in a loop, you’ll just lose performance, the loop still gets processed. If you exceed the amount of memory in a vertex shader, you simply can’t process that data. This does make the hardware implementation easier, but it makes the software implementation harder. If vertex shaders didn’t have instruction limits or constant limits, the fragment based processing system would be infallible. It’s a shame that underlying hardware constraints have passed the whole way up the API to the game programmer.

In the future, these limits will increase, but as long as the new limits are within an order of magnitude, it will still be possible to reach the constant limit with existing animation methods.

Compatibility

For most PC systems, backwards compatibility has always been a bit of a headache. In a perfect world, all game-players would have a useable version of the game, even if they’re running on a P-60 with a standard 2D graphics card. Unfortunately, it’s impossible to write games that can run on any hardware; a cut-off point must always be made. For the moment, over half of the buying public are running hardware which can accelerate the fixed-function pipeline in hardware, but a very small percentage have hardware which can accelerate vertex shaders. So, until next generation graphics cards make up ~10% of the market, the only people that really need to worry about vertex shaders are people who are working on OEM titles, and the really big companies who are keen to use all the latest graphical effects. Although, that said, vertex shader emulation does mean that particularly cool types of vertex processing can still be carried out in software on older hardware T&L cards.

Pixel shaders are also fairly rare in the marketplace at the moment, and, as there is no possibility of emulation on older hardware, the texture cascade system is going to be around for a good few years to come. You may remember that one of the biggest problems with the texture cascade system is that you have to program for lots of different type of hardware. Pixel shaders promised to vastly reduce the amount of compatibility code in game engines. Unfortunately, DX8.1 has shown us that things might not be moving in the perfect direction. For DX8, we had two types of pixel shader, PS1.0 and PS1.1. However DX8.1 introduces PS1.2, PS1.3 and PS1.4. If this carries on for DX9 and DX10, we could end up supporting about ten different versions of pixel shaders, and each one will probably correspond to a small number of hardware devices. It would seem more sensible to only increment the version numbers for each major release, and then, to only increase them by one.

Summary

Overall, it’s going to be impossible not to use vertex shaders and pixel shaders within a few years’ time. The hardware vendors and Microsoft all like the new paradigm, so closing your eyes to the shader implementations won’t get you anywhere!

It’s a shame that a lot of the work that used to be done by the driver has been moved into the domain of the games programmer, but we’re just going to have to learn to make the most of it. The currently available vertex shader implementation makes it very difficult to get much out of shaders without writing complicated API wrappers such as the fragment-based system described above. With any luck, DX9 will introduce flow control into the vertex shader architecture. At that point, we should be able to carry out the lighting with a constant piece of code for each vertex shader. The lighting itself can be specified in the constant memory, but it looks like the code-size limit will remain, so it may still be necessary to have a simple form of fragment processing, in order to avoid reaching this limit.

There is no doubt that the shader architecture opens up new possibilities within the hardware. The software implementation of vertex shaders is good enough to emulate useful vertex shaders on older hardware, and if you’re writing technical demonstrations, you’ll love the freedom that the shader architecture gives you. For game engines, you’ll need to look at what shaders will give you, versus the amount of work shader support will require.

Hopefully this article has introduced a few methods that you may be able to use to open up the shader architecture within your own projects, as well as shedding some light on the pitfalls associated with them. It’s not a perfect architecture, but it does let us produce some great effects.







Вам также может понравиться
U4cgMqDxkeRdvWncNHXoM6 970 80 png
Читать
  • Видеокарты

Лучшие видеокарты для игр в 2026 году

  • THG
  • 13.01.2026
luchshaya videokarta 01
Читать
  • Видеокарты
  • Подборки

Лучшая видеокарта для игр: текущий анализ рынка

  • Редакция THG
  • 22.11.2024
ac20619a1ab87a27a2002ae94e699459
Читать
  • Видеокарты

Выбираем подержанную видеокарту — THG.RU

  • 08.09.2020
13eb5823092f9dfdac4d5a55e77bafd4
Читать
  • Видеокарты

Всё, что мы знаем об Nvidia RTX 3080 и Ampere — THG.RU

  • 18.06.2020
7d7286276a25ac06cbf5759f100a10a2
Читать
  • Видеокарты

Иерархия видеокарт AMD и Nvidia: сравнительная таблица — THG.RU

  • 30.05.2019
6059a3d20c04b90170b9b5fade17f520
Читать
  • Видеокарты

Какие видеокарты лучше: референсные или партнёрские? — THG.RU

  • 08.05.2019
5981eb2d43d076d3a26adcd01c7aabf6
Читать
  • Видеокарты

AMD Radeon VII: обзор и тест видеокарты для игр в 4K — THG.RU

  • 15.03.2019
8057c28a42e248ccb252112de8ef06cc
Читать
  • Видеокарты

Nvidia GeForce RTX 2070 Founders Edition: обзор и тест видеокарты — THG.RU

  • THG
  • 29.01.2019

Добавить комментарий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *


Подписывайтесь на наши страницы в социальных сетях
Telegram

Свежие статьи

  • Почему конец партии в дураке решает расчет, а не везение
  • Обзор ноутбука ASUS ROG Zephyrus Duo 2026 (GX651)
  • Тонометр на запястье и титан с керамикой: в России стартовали продажи HUAWEI WATCH D3 и HUAWEI WATCH 6
  • М.Видео начинает предзаказ на HUAWEI MatePad Air: ультратонкий планшет с OLED-экраном PaperMatte
  • Обзор игрового кресла Zone 51 Chevron: крепкий середняк с претензией на звание боевого товарища
Популярные записи
  • Напряжённая карточная партия при свечах 1
    Почему конец партии в дураке решает расчет, а не везение
    • 12.11.2026
  • Без имени 2
    Обзор ноутбука ASUS ROG Zephyrus Duo 2026 (GX651)
    • 14.10.2026
  • WATCH 6 продакт фото2 3
    Тонометр на запястье и титан с керамикой: в России стартовали продажи HUAWEI WATCH D3 и HUAWEI WATCH 6
    • 14.10.2026
  • Wooki 晴光蓝AiryBlue 4
    М.Видео начинает предзаказ на HUAWEI MatePad Air: ультратонкий планшет с OLED-экраном PaperMatte
    • 29.09.2026
  • Photo 2026 09 28 15 47 5
    Обзор игрового кресла Zone 51 Chevron: крепкий середняк с претензией на звание боевого товарища
    • 28.09.2026
Последние записи
  • Contract signing meeting stockcake
    Чем созаёмщик отличается от поручителя
    • 28.09.2026
  • 10USB30
    10 лучших флешек USB 3.0: сравнительный обзор на любой бюджет
    • 05.07.2026
  • 17
    HONOR MagicPad 4: ультратонкий планшет с процессором уровня ПК стартовал в России
    • 04.07.2026
Категории
  • 4G
  • Аудио и видео
  • Без рубрики
  • Бизнес и рынок
  • Видеокарты
  • Домашний компьютер
  • Игры и индустрия
  • Конкурсы
  • Накопители
  • Новости
  • Обзоры
  • Образование
  • Периферия
  • Платформы
  • Подборки
  • Проекторы и мониторы
  • Процессоры
  • Сети и WiFi
  • Смартфоны и ноутбуки
  • Собери сам
  • Софт и утилиты
  • Статьи
  • Техника для дома и сада
  • Фото
Архив
THG
  • Обзоры
  • Статьи
  • Подборки
  • Новости
  • Форум
  • Контакты
  • Главная
IT-новости, обзоры смартфонов, гаджетов и компьютерного железа

Powered by
Necessary cookies enable essential site features like secure log-ins and consent preference adjustments. They do not store personal data.
None
Functional cookies support features like content sharing on social media, collecting feedback, and enabling third-party tools.
None
Analytical cookies track visitor interactions, providing insights on metrics like visitor count, bounce rate, and traffic sources.
None
Advertisement cookies deliver personalized ads based on your previous visits and analyze the effectiveness of ad campaigns.
None
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
None
Powered by