############################
The CPU Programming Pipeline
############################


The architecture of a CPU material exactly matches the architecture of GPU materials: CPU shaders are added to rendering passes exactly as GPU shaders are. In fact, there's no difference between CPU and GPU shaders: both are based on the ``RED::RenderShader`` and ``RED::StateShader`` classes. The only differences are in the definition of the shader target (software shader are using ``RED::HW_SOFT_TRACER``) and of programs, that are made of C++ compiled code.

``RED::RenderShader`` in software follows the same binding mechanics as GPU shaders for the ``RED::RenderCode`` part, to bridge geometrical data directly to the shader. However, unlike GPU shaders, a CPU shader has only one program, that is declared as both the vertex and pixel shader from the HOOPS Luminate ``RED::RenderShader`` API.

*****************************
The Software Program Callback
*****************************

The software shader program is only defined by a single callback following the ``RED::SOFT_SHADER_CALLBACK`` prototype:

.. code:: cpp
    
  #include "REDSoftShaderCallback.h"

  RED_RC SoftwareShader( RED::SoftFrameBufferSample&       fbsample,
                        const RED::ISoftRayContext&       rayctx,
                        const RED::ISoftShaderContext&    shaderctx,
                        const RED::ISoftRenderingContext& renderctx,
                        const RED::Version&               version )
  {
    fbsample._out_color[0] = 1.0;
    fbsample._out_color[1] = 1.0;
    fbsample._out_color[2] = 1.0;
    fbsample._out_color[3] = 1.0;
    
    return RED_OK;
  }


The method must return 'fbsample._out_color'. The ``RED::SoftFrameBufferSample`` is the class that describes all the properties of the frame buffer for the considered pixel sample at the time of the shading call.

Several specific API objects are in charge of providing all the necessary informations to the software shader:

  * ``RED::ISoftRayContext``: this interface gives an access to all current geometrical informations of the shaded point in the ray-tree: the hit primitive, the current depth in the ray-tree, our thread number, etc. It also provides texture sampling helpers.
  * ``RED::ISoftShaderContext``: this is the shader parameters. You'll find the ``RED::RenderCode`` and all local parameters that were declared during the shader setup.
  * ``RED::ISoftRenderingContext``: this interface returns all rendering options for the current frame.

The ``RED::Version`` used in the method prototype is here to help versioning shaders whenever shader inputs evolve over releases.

From the ``RED::ISoftRayContext``, all informations relative to our position in the ray-tree are stored and can be leveraged to figure out what to do. Most common uses for the current ray context are:

  * Access the current position in space: ``RED::ISoftRayContext::GetWCSHit``.
  * Access the interpolated normal at the hit point: ``RED::ISoftRayContext::GetWCSNormal``.
  * Sample a texture: ``RED::ISoftRayContext::SampleTexture``.

.. note::
  
  The software shading method matches the hardware shading methods: we still have input geometry channels that are connected to the shading using a ``RED::RenderCode`` instance. The main difference between hardware and software shading is about the fact that we have one single shader for the vertex shader and pixel shader stages in the hardware.

By default, the engine launches a number of rendering threads equal to ``RED::OPTIONS_RAY_MAX_THREADS``. All software shading methods are called in this multi-threaded context.

.. include:: /tasks/ta_ca/ta_ca_material/tk_defining_software_shader_dll_entry_point.rst

As an alternative, software shading methods can be defined in the executable program itself:

.. include:: /tasks/ta_ca/ta_ca_material/tk_defining_software_shader_local_entry_point.rst

*************************
The Software Shading Loop
*************************

As explained in the ':doc:`/book/subjects/bk_bm/bk_bm_the_shading_pipeline`' page, in GPU mode the shader programs contained in the ``RED::MTL_LIT`` pass are executed one time for each light in the scene. The pass is cumulative. Hence, GPU shaders must be written as one step of the loop.

Unlike the GPU mode, the software shader callbacks defined in the ``RED::MTL_LIT`` pass are called only once. The pass is additive. The cumulative loop through the lights must be handled by the user in the shader callback.

The lights can be accessed via the ``RED::ISoftRenderingContext::GetLightsCount`` and ``RED::ISoftRenderingContext::GetLight`` methods. A call to ``RED::ISoftRayContext::PrepareLights`` is mandatory before accessing the lights in order to setup them before the shading.

It is up to the writer to choose it's light sampling method. To facilitate the sampling, HOOPS Luminate provides useful built-in functions to do it: ``RED::ISoftLight::NeedSampling``, ``RED::ISoftLight::StartSampling`` and ``RED::ISoftLight::GetNextWCSSample``. The methods are already taking shadows and light source attenuation into consideration.

Light source culling must be performed manually: the engine does not make any assumption. The ``RED::ISoftLight::GetAttenuation`` method allows to do it.

.. include:: /tasks/ta_ca/ta_ca_material/tk_iterating_over_lights_software_shader.rst
