HDK
|
The GL3 Viewport uses modern GPU features, such as Vertex Buffer Objects (VBOs), shaders, FrameBuffer Objects (FBOs), Uniform Buffer Objects (UBOs) and special texture formats (integer textures, 2D texture arrays). It is based on OpenGL 3.3, and its primary goal is to shift more work away from the CPU and onto the GPU. Less work for the CPU means that geometry updates can occur faster, though at the expense of the viewport frame rate because the GPU is working harder. Generally this is a good tradeoff, as frame rates for tumbling for most models were above the 60fps mark at which the monitor can display them.
The result of this is that the GL3 viewport requires at least mid-range GPU hardware to run effectively, with a recommended minimum of 1GB of VRAM.
The GL3 Viewport also renders all geometry using shaders. Version 150 of the OpenGL shading language (GLSL) is used for Houdini's native primitives. However, this restriction doesn't extend to user GLSL shaders, providing they follow some basic rules:
Unlike GL2, GL3 vertex shaders use inputs that are named the same as their Houdini counterparts. For example:
These inputs are all point or detail attributes (varying or constant). Access to primitive or vertex attributes must be done in a geometry shader:
Any Houdini attribute type can be sampled this way, as long as it has between 1 and 4 components. Attributes with greater than 4 components need to be split into multiple GL attributes.
String attributes are not supported because GLSL does not support strings; partitioning of the geometry based on the string table is one way to get around this restriction. Each partition can them be setup uniquely and drawn (this is how shop_material_path is handled).
OpenGL has minimum limits for both the number of vertex shader inputs and the number of textures that can be accessed in a shader stage. For GL3.3, this is 16 vertex inputs and 16 textures, though specific implementations may have higher limits. Matrix vertex inputs take up more than one attribute location (2 for mat2, 3 for mat3, 4 for mat4), and double precision inputs may take up more than one location. It is possible to get around the vertex input limit by combining two or more Houdini attributes in a single GL attribute (say, Cd+Alpha, or uv+uv2), or by using a Texture Buffer Object to sample an attribute using texelFetch().
Because GL3 uses generic vertex inputs, rendering a GL3 object without a shader will not render anything. While shaders may seem like a bit of a burden initially, they are much easier to debug and maintain because the amount of GL state used by shaders is substantially reduced. While the fixed function state can be difficult to determine, a shader's source is is easy to view.
The GL3 rendering environment is made up of uniforms and uniform blocks. Uniforms are used for most of the global state, while uniform blocks tend to represent actual objects (lights, materials). Uniform blocks are buffer objects that can be easily seperated from the shader state, which is handy for keeping them with the C++ object that they represent.
The lighting state is set up in uniform blocks for lights 0 to 10.
These uniform blocks can be set up using RE_LightList::bindForShader(). The light list can be queried from GR_CommonDispOptions::getLightList().
You can also use the Houdini builtin GLSL functions, such as HOUlightingModel(), to handle lighting for you.
The function will automatically link into your shader if its name is found in the shader and it is loaded via RE_Shader. Otherwise, it can be found in glsl/houlib/GL32/lighting_model.func.
High Quality lighting uses a deferred shading scheme, so lighting should not be computed in this case. HQ Lighting is active if glH_MaterialPass is 1.
The material block can be set up using RE_Material::updateShaderForMaterial(). This will populate the material uniform block with values form the current material. A material also has texture samplers which cannot reside inside a uniform block, so additional sampler uniforms are required.
Every material has four color components that can be applied during lighting (multiplied by the shader-computed lighting components) and two alpha components. The default alpha is for eye rays perpendicular to the surface; alpha_para is for eye rays parallel to its silhouette edges. Most of the time these will be the same, but for simulating the fresnel of glass, they can be different.
The next three sections deal with lighting maps - bump, normal, specular and reflection (environment) maps.
Bump maps create the illusion of an uneven surface without modifying the geometry itself by perturbing normals on a per-pixel basis. The bump map does double duty supporting bump and normal maps. If has_bump_maps is true, a bump or normal map exists. The bumpComps determines the type of map being used. A 1 component map is considered to be a height map, and the gradients of the map are determined to perturb the normal. A 2 component map is considered to be a regular uv bump map. A 3 component map is considered to be a normal map, which replaces the normals entirely. The bumpBias specifies whether the map's range is [0,1], which would be a regular 8b map, or [-1,1] for a floating point format. bumpInvert will invert the direction of the bumps, while bumpScale will exagerate (>1) or diminish (<1) the bumps.
Specular maps allow areas to be designated as shiny and others dull. The RGB components of a specular map define the specular reflection color, while the alpha can adjust the shininess of the surface (if specularShinyAdjust is true). The shinyRange parameter maps the [0,1] alpha channel to the extents of the shininess (min 0, max 128).
The environment map allows the surface to appear to reflect its surroundings (the contents of the map). Environment maps are cubemaps. The reflection intensity can be adjusted with envScale, and the entire map rotated around the object using envRotate.
In addition to the lighting and material blocks, there are also builtin Houdini uniforms which can be accessed from any shader stage: