Hardware Based Rendering of 3D Geometry

Create Hardware and Render a 3D Geometry

To render a 3D geometry, a shader, buffers and render state are required. None of them can work without each other.

  • Buffers - Triangle lists are individual triangles specified in an array that is sometimes referred to as a buffer. In a triangle list, each triangle is individually specified. Points of a triangle can be shared by using indices to reduce the amount of data that must be passed to the graphics hardware.
  • Shaders - It defines how to transform the triangles from world space into screen space and calculate the final pixel color in GPU side
  • Render States - It provides parameters for the GPU to rasterize the triangles into pixels.

The OpenGL Shading Language (GLSL) is the standard high level shading language for the OpenGL graphics API. The InitRenderer method in AssetBrowser/Controls/RenderView.cs file under the demo application (name:AssetBrowser) demonstrates the simple use of GLSL using Aspose.3D API. There are three shader types commonly used: Vertex Shaders, Fragment Shaders and Geometry Shaders.

GLSLSource class tells the renderer, the source code is for OpenGL shading language, it can be compiled to ShaderProgram class. The ShaderVariable class defines the variables used in the shader. The VariableSemantic class is used to identify the shader variable’s semantic, Aspose.3D renderer will automatically prepare shader variable values depends on the semantics.

Programming Sample for Shader

This code example initializes renderer and Shader for the grid. You can download complete working project of this example from here.

// For complete examples and data files, please go to https://github.com/aspose-3d/Aspose.3D-for-.NET
private void InitRenderer()
{
// Create a default camera, because it's required during the viewport's creation.
camera = new Camera();
Scene.RootNode.CreateChildNode("camera", camera);
// Create the renderer and render window from window's native handle
renderer = Renderer.CreateRenderer();
// Right now we only support native window handle from Microsoft Windows
// We'll support more platform on user's demand.
window = renderer.RenderFactory.CreateRenderWindow(new RenderParameters(), Handle);
// Create 4 viewports, the viewport's area is meanless here because we'll change it to the right area in the SetViewports later
viewports = new[]
{
window.CreateViewport(camera, Color.Gray, RelativeRectangle.FromScale(0, 0, 1, 1)),
window.CreateViewport(camera, Color.Gray, RelativeRectangle.FromScale(0, 0, 1, 1)),
window.CreateViewport(camera, Color.Gray, RelativeRectangle.FromScale(0, 0, 1, 1)),
window.CreateViewport(camera, Color.Gray, RelativeRectangle.FromScale(0, 0, 1, 1))
};
SetViewports(1);
//initialize shader for grid
GLSLSource src = new GLSLSource();
src.VertexShader = @"#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 matWorldViewProj;
void main()
{
gl_Position = matWorldViewProj * vec4(position, 1.0f);
}";
src.FragmentShader = @"#version 330 core
out vec4 color;
void main()
{
color = vec4(1, 1, 1, 1);
}";
// Define the input format used by GLSL vertex shader the format is struct ControlPoint { FVector3 Position;}
VertexDeclaration fd = new VertexDeclaration();
fd.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Position);
// Compile shader from GLSL source code and specify the vertex input format
gridShader = renderer.RenderFactory.CreateShaderProgram(src, fd);
// Connect GLSL uniform to renderer's internal variable
gridShader.Variables = new ShaderVariable[]
{
new ShaderVariable("matWorldViewProj", VariableSemantic.MatrixWorldViewProj)
};
SceneUpdated("");
}

Programming Sample for the Buffer and Render State

This code example initializes the buffer and render state for the grid.

// For complete examples and data files, please go to https://github.com/aspose-3d/Aspose.3D-for-.NET
class Grid : ManualEntity
{
public Grid(Renderer renderer, ShaderProgram shader)
{
// Render state for grid
RenderState = renderer.RenderFactory.CreateRenderState();
RenderState.DepthTest = true;
RenderState.DepthMask = true;
this.Shader = shader;
// Define the format of the control point to render the line
VertexDeclaration vd = new VertexDeclaration();
vd.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Position);
// and create a vertex buffer for storing this kind of data
this.VertexBuffer = renderer.RenderFactory.CreateVertexBuffer(vd);
// Draw the primitive as lines
this.DrawOperation = DrawOperation.Lines;
this.RenderGroup = RenderQueueGroupId.Geometries;
List<FVector3> lines = new List<FVector3>();
for (int i = -10; i <= 10; i++)
{
// Draw - line
lines.Add(new FVector3(i, 0, -10));
lines.Add(new FVector3(i,0, 10));
// Draw | line
lines.Add(new FVector3(-10, 0, i));
lines.Add(new FVector3(10, 0, i));
}
// Put it to vertex buffer
VertexBuffer.LoadData(lines.ToArray());
}
}