This commit is contained in:
Thomas Forgione 2019-10-02 11:32:47 +02:00
parent 947a32d970
commit a1676138c9
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
2 changed files with 99 additions and 30 deletions

View File

@ -1,8 +1,10 @@
A 3D streaming system is a system that collects 3D data and dynamically renders it.
The previous chapter voluntarily remained vague about what \emph{3D data} actually is.
This chapter presents in detail what 3D data is and how it is reenderer, and give insights about interaction and streaming by comparing the 3D case to the video one.
\section{What is a 3D model?}
Before talking about 3D streaming, we need to define what is a 3D model and how it is rendered.
\subsection{Content of a 3D model}
\subsection{3D data}
A 3D model consists in a set of data.
\begin{itemize}
@ -19,7 +21,7 @@ A 3D model encoded in the OBJ format typically consists in two files: the materi
\paragraph{}
The materials file declare all the materials that the object file will reference.
A material consists in name, and other photometric properties such as ambient, diffuse and specular colors, as well as texture maps.
Each face correspond to a material and a renderer can use the material's information to render the faces.
Each face correspond to a material and a renderer can use the material's information to render the faces in a specific way.
A simple material file is visible on Listing~\ref{i:mtl}.
\paragraph{}
@ -63,26 +65,94 @@ An example of object file is visible on Listing~\ref{i:obj}.
\subsection{Rendering a 3D model\label{i:rendering}}
To be able to render a model, it is first required to send the data (vertices, textures coordinates, normals, faces and textures) to the GPU, and then only the rendering can be done.
Then, to render a 3D model, the objects from the model are traversed, the materials and textures are bound to the target on which the rendering will be done, and then, \texttt{glDrawArray} or \texttt{glDrawElements} function is called.
To understand how performance is impacted by the structure of the model, we need to realize two things:
A typical 3D renderer follows Algorithm~\ref{f:renderer}.
\newcommand\mycommfont[1]{\footnotesize\ttfamily\textcolor{blue}{#1}}
\SetCommentSty{mycommfont}
\SetNoFillComment%
\begin{algorithm}[th]
\SetKwData{Texture}{texture}
\SetKwData{Object}{object}
\SetKwData{Geometry}{geometry}
\SetKwData{Textures}{all\_textures}
\SetKwData{Object}{object}
\SetKwData{Scene}{scene}
\SetKwData{True}{true}
\SetKwFunction{LoadGeometry}{load\_geometry}
\SetKwFunction{LoadTexture}{load\_texture}
\SetKwFunction{BindTexture}{bind\_texture}
\SetKwFunction{Draw}{draw}
\tcc{Initialization}
\For{\Object\in\Scene}{%
\LoadGeometry(\Object.\Geometry)\;
\LoadTexture(\Object.\Texture)\;
}
\BlankLine%
\BlankLine%
\tcc{Render loop}
\While{\True}{%
\For{\Object\in\Scene}{%
\BindTexture{\Object.\Texture}\;
\Draw{\Object.\Geometry}\;
}
}
\caption{A rendering algorithm\label{f:renderer}}
\end{algorithm}
The first task the renderer needs to perform is sending the data to the GPU\@: this is done in the loading loop at the beginning.
This step can be slow, but it is generally acceptable since it only occurs once at the beginning of the program.
Then, the renderer starts the rendering loop: at each frame, it renders the whole scene.
During the rendering loop, there are two things to consider regarding performances:
\begin{itemize}
\item calling many times \texttt{glDrawArray} on small arrays is considerably slower than calling it once on a big array;
\item calling \texttt{glDrawArray} on a small array is faster than calling it on a big array.
\item obviously, the more faces a geometry contains, the slower the \texttt{draw} call is;
\item the more objects in the scene, the more overhead at each step of the loop.
\end{itemize}
However, due to the way the materials and textures work, we are forced to call \texttt{glDrawArray} at least as many times as there are materials in the model.
Minimizing the numbers of materials used in a 3D model is thus critical for rendering performances.
The way the loop works forces objects with different textures to be rendered separately.
An efficient renderer keeps the number of objects in a scene low to avoid introducing overhead.
Another way to improve the performance of rendering is \textbf{frustum culling}.
Frustum culling is a technique that consists in avoiding drawing objects that are not in the field of view of the user's camera.
It is particularly efficient when they are many objects in a scene since it gives potential for skips.
However, an important feature of 3D engine regarding performance is frustum culling.
The frustum is the viewing volume of the camera.
Frustum culling consists in avoiding rendering objects that are outside the viewing volume of the camera.
Algorithm~\ref{f:frustum-culling} is a variation of Algorithm~\ref{f:renderer} with frustum culling.
These two aspects are somehow contradictory, and to have greatest performance for 3D rendering, one must ensure that:
\begin{itemize}
\item the least amount of materials are used, and most objects that share materials are drawn together in a single \texttt{glDrawArray} call;
\item objects are not all drawn together and grouped together depending on their location to keep the frustum culling efficient.
\end{itemize}
\begin{algorithm}[th]
\SetKwData{Texture}{texture}
\SetKwData{Object}{object}
\SetKwData{Geometry}{geometry}
\SetKwData{Textures}{all\_textures}
\SetKwData{Object}{object}
\SetKwData{Scene}{scene}
\SetKwData{True}{true}
\SetKwData{CameraFrustum}{camera\_frustum}
\SetKwFunction{LoadGeometry}{load\_geometry}
\SetKwFunction{LoadTexture}{load\_texture}
\SetKwFunction{BindTexture}{bind\_texture}
\SetKwFunction{Draw}{draw}
\tcc{Initialization}
\For{$\Object\in\Scene$}{%
\LoadGeometry(\Object.\Geometry)\;
\LoadTexture(\Object.\Texture)\;
}
\BlankLine%
\BlankLine%
\tcc{Render loop}
\While{\True}{%
\For{$\Object\in\Scene$}{%
\If{$\Object\cap\CameraFrustum\neq\emptyset$}{%
\BindTexture{\Object.\Texture}\;
\Draw{\Object.\Geometry}\;
}
}
}
\caption{A rendering algorithm with frustum culling\label{f:frustum-culling}}
\end{algorithm}
A renderer that uses a single object avoids the overhead, but fails to benefit from frustum culling.
A better renderer ensures to have objects that do not spread across the whole scene, since that would lead to a useless frustum culling, and many objects to avoid rendering the whole scene at each frame, but not too many objects to avoid suffering from the overhead.

View File

@ -15,28 +15,27 @@ A 3D streaming client has lots of tasks to accomplish:
This opens multiple problems that we need to take care of.
\subsection{Content preparation}
\paragraph{Content preparation.}
% Any preprocessing that can be done on our 3D data gives us a strategical advantage since it consists in computations that will not be needed live, neither for the server nor for the client.
% Furthermore, for streaming, data needs to be split into chunks that are requested separately, so perparing those chunks in advance can also help the streaming.
Before streaming content, it needs to be prepared.
This includes but is not limited to compression and segmentation.
The segmentation of the content into chunks is particularly important for streaming since it allows transmitting only a portion of the data to the client, that it can render before downloading more chunks.
Content preparation also includes compression.
One of the question this thesis has to answer is \emph{what is the best way to prepare 3D content so that a client can benefit from it?}
An open question of this thesis is \emph{how do we determine how useful is a chunk of data depending on the user's position?}
\subsection{Streaming policies}
Once our content is prepared and split in chunks, one needs to be able to rate those chunks depending on the user's position.
A chunk that contains data in the field of view of the user should have a higher score than a chunk outside of it; a chunk that is close to the camera should have a higher score than a chunk far away from the camera, etc\ldots.
This rating should also include other contextual parameters, such as the size of a chunk, the bandwidth, the user's behaviour, etc\ldots.
\paragraph{Streaming policies.}
Once our content is prepared and split in chunks, a client needs to determine which chunks it needs to download.
A chunk that contains data in the field of view of the user is more relevant than a chunk outside of it; a chunk that is close to the camera is more relevant than a chunk far away from the camera, etc\ldots.
This should also include other contextual parameters, such as the size of a chunk, the bandwidth, the user's behaviour, etc\ldots.
The most important question we have to answer is \emph{how do we determine which chunks need to be downloaded depending on the chunks themselves and the user's interactions?}
\subsection{Evaluation}
\paragraph{Evaluation.}
In such systems, the two most important criteria for evaluation are quality of service, and quality of experience.
The quality of service is a network-centric metric, which considers values such as throughput.
The quality of experience is a user-centric metric, and can only be measured by asking how users feel about a system.
To be able to know which streaming policies, one needs to know \emph{how can we compare streaming policies and evalute the impact of their parameters in terms of quality of service and quality of experience?}
To be able to know which streaming policies are best, one needs to know \emph{how can we compare streaming policies and evalute the impact of their parameters in terms of quality of service and quality of experience?}
\subsection{Implementation}
\paragraph{Implementation.}
The objective of our work is to setup a client-server architecture that answers the problems mentioned earlier (content preparation, chunk utility, streaming policies).
In this regard, we have to find out \emph{how do we build this architecture while keeping the computational load on the server low so it can scale and the client efficient so that it has resources to perform its many tasks?}