Carna  Version 3.0.1
Classes | Public Member Functions | Static Public Member Functions | Public Attributes | Protected Member Functions | Friends | List of all members
Carna::base::Material Class Reference

Specifies the shader and it's configuration that are to be used for rendering a Geometry node with a MeshRenderingStage. Custom implementations could also tweak the render state. More...

#include <Material.h>

+ Inheritance diagram for Carna::base::Material:
+ Collaboration diagram for Carna::base::Material:

Classes

class  ManagedInterface
 Represents an acquisition of video resources from a particular Material. This realizes the RAII idiom. More...
 

Public Member Functions

void addParameter (ShaderUniformBase *uniform)
 Records uniform as shader parameter. This will be uploaded to the shader when the material is activated. More...
 
template<typename ParameterType >
void setParameter (const std::string &name, const ParameterType &value)
 
void clearParameters ()
 Removes all previously set parameters.
 
void removeParameter (const std::string &name)
 Removes the parameter named name if it exists.
 
bool hasParameter (const std::string &name) const
 Tells whether a paramter named name exists.
 
const ShaderUniformBaseparameter (const std::string &name) const
 References the paramter named name. More...
 
virtual bool controlsSameVideoResource (const GeometryFeature &other) const override
 Tells whether this instance maintains the same video resources like other. More...
 
virtual ManagedInterfaceacquireVideoResource () override
 Acquires the video resources from this GeometryFeature by returning new instance of a class derived from ManagedInterface, that realizes the RAII idiom. Refer to its documentation for details. May return nullptr if this GeometryFeature does not provide any video resources.
 
- Public Member Functions inherited from Carna::base::GeometryFeature
unsigned int videoResourceAcquisitionsCount () const
 Tells current number of video resource acquisitions.
 
void release ()
 Denotes that this object is no longer required and may be deleted as soon as it is valid to delete it. More...
 
void addTo (Geometry &sceneGraphNode, unsigned int role)
 Puts this geometry feature on the sceneGraphNode. More...
 
void removeFrom (Geometry &sceneGraphNode)
 Removes this geometry feature from the sceneGraphNode. More...
 

Static Public Member Functions

static Materialcreate (const std::string &shaderName)
 Instantiates. Call release when you do not need the object any longer.
 

Public Attributes

const std::string shaderName
 Identifies this material's shader.
 

Protected Member Functions

 Material (const std::string &shaderName)
 Instantiates.
 
virtual ~Material ()
 Deletes.
 
- Protected Member Functions inherited from Carna::base::GeometryFeature
 GeometryFeature ()
 Instantiates.
 
virtual ~GeometryFeature ()
 Deletes and logs an error if video resources are leaked.
 

Friends

class GeometryFeature
 

Detailed Description

Specifies the shader and it's configuration that are to be used for rendering a Geometry node with a MeshRenderingStage. Custom implementations could also tweak the render state.

Rendering Pipeline

The core part of a material is the shader, which requires a basic understanding of the rendering pipeline. A very good explanation can be found here: http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/pipeline33/ Nevertheless, lets pass through the most important aspects of the pipeline. The pipeline consists of stages, that are distinguished by whether they are programmable or not. Programmable stages are called shaders.

  1. The first stage always is the vertex shader that is invoked once for each vertex from the vertex buffer. It takes one vertex per invocation as input, transforms it and writes it to the output. Typically the output vertices are written as clipping coordinates.
  2. Within the primitive assembly stage the vertices are assembled to primitives according to the index buffer.
  3. The optional geometry shader is invoked once for each primitive. For each invocation, it writes an arbitrary number of primitives as output. This means that the geometry shader can be used for culling primitives as well as for the generation of new ones.
  4. The rasterization and interpolation stage maps the primitives on top of a grid, whose cells are called fragments. Fragments are basically pixels, but they are given in window coordinates, hence they have a depth component in particular.
  5. The fragment shader is invoked once for each fragment of the pritimive. It either writes the fragment's attributes like its color and its depth, or it discards the fragment. It is neither possible to generate new fragments, nor to change other fragment's coordinates but its depth.
  6. The last stage maps the primitive's fragments to the color buffer's pixels by application of alpha blending. It also performs tests, like the depth test, on each fragment.

Note that the depth test might be performed within stage 4 already, if stage 5 does not alter the precomputed fragment depth. This is usually faster, because less fragments need to be processed by stage 5.

Custom Materials

As already mentioned in the section above, the core part of a material is its shader. A shader, actually the shader program, consists of a vertex shader and a fragment shader at least. It may also have a fragment shader, which is optional. All three of these are explained in the section above.

So the first step in creating a new material most likely will be the implementation of a vertex and a fragment shader.

Vertex Shaders

A typical vertex shader looks like this:

1 #version 330
2 uniform mat4 modelViewProjection;
3 layout( location = 0 ) in vec4 inPosition;
4 void main()
5 {
6  vec4 clippingCoordinates = modelViewProjection * inPosition;
7  gl_Position = clippingCoordinates;
8 }

Line 1 specifies the GLSL version that the compiler should use to build the code. Line 2 declares a variable, whose value will be set from code that runs on the CPU. The keyword uniform reflects the fact the value will be the same for each processed vertex. Line 3 declares the vertex format. The main function is invoked for each processed vertex. The example code above assumes that the vertices are stored in model space within the vertex buffer and transforms them to clipping coordinates.

Following uniform variables will be set by the Material class automatically, if declared:

Fragment Shaders

Lets take a look at an exemplary fragment shader:

1 #version 330
2 uniform vec4 color;
3 out vec4 gl_FragColor;
4 void main()
5 {
6  gl_FragColor = vec4( color );
7 }

Line 1 declares the GLSL version, just like it was did for vertex shaders. Vertex and fragment shaders, that are going to be used together as a single shader program must also use the same GLSL version. Line 2 declares a variable, whose value will be set when the shader is triggered. Note that the keyword uniform reflects the same intuitive meaning as it did in the vertex shader example above. Line 3 declares a variable, that the fragment shader will write its output to. You won't need a different declaration than this, unless you are going to render to multiple color buffers at once, which is an advanced technique. Just like for vertex shaders, the main function of the fragment shader will be executed once for each fragment. The shader code above colors the whole rendered object in a uniform color.

Integration into Materials

The Material class acquires its shader objects from the ShaderManager, which ensures that each shader is built just once and not each time someone requests it. So everything one has to do is to ensure that the ShaderManager will be able to locate the shader sources:

using namespace Carna;
base::ShaderManager::instance().setSource( "myShader.vert", srcVert );
base::ShaderManager::instance().setSource( "myShader.frag", srcFrag );

This needs to be done before the material first tries to acquire the shader, i.e. before the geometry node, the material is attached to, is rendered.

The suffixes .vert and .frag are important. You will be able to reference the shader from a Material object by setting its shaderName to myShader.

Author
Leonid Kostrykin
Date
22.2.15 - 18.3.15

Definition at line 174 of file Material.h.

Member Function Documentation

void Carna::base::Material::addParameter ( ShaderUniformBase uniform)

Records uniform as shader parameter. This will be uploaded to the shader when the material is activated.

Any previously set parameters with the same name are overriden.

virtual bool Carna::base::Material::controlsSameVideoResource ( const GeometryFeature other) const
overridevirtual

Tells whether this instance maintains the same video resources like other.

This implementation checks whether other also is a Material and if yes, whether its shaderName is the same.

Implements Carna::base::GeometryFeature.

const ShaderUniformBase& Carna::base::Material::parameter ( const std::string &  name) const

References the paramter named name.

Precondition
hasParameter(name) == true
template<typename ParameterType >
void Carna::base::Material::setParameter ( const std::string &  name,
const ParameterType &  value 
)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Definition at line 306 of file Material.h.


The documentation for this class was generated from the following file: