OpenGL.Shader:4-GPUカットシーン、並列操作の分析

OpenGL.Shader:4-GPUカットシーン、並列操作の分析

 

この記事は、シェーダーコーディング仕様の学習を続けるための2つの簡単な例で構成されています。そして、シェーダー拡張並列操作の概念。対応するプロジェクトアドレス:https//github.com/MrZhaozhirong/NativeCppApp 

最初の例のレンダリング。同じことが前の記事のコンテンツのキューブモデルデータに基づいています。関連するコードは表示されません。必要な学生はgithubで入手できます。次に、シェーダープログラムの関連コードの分析と学習に焦点を当てます。


#include "GPUMixShaderProgram.h"
#include "ShaderHelper.h"

/**
 * 正方体动态渐变 着色器程序
 */
GPUMixShaderProgram::GPUMixShaderProgram()
{
    const char * vertexShaderResourceStr  = "uniform mat4    u_Matrix;\n\
                                             attribute vec4  a_Position;\n\
                                             attribute vec2  a_uv;\n\
                                             varying vec2    out_uv;\n\
                                             void main()\n\
                                             {\n\
                                                 out_uv      =   a_uv;\n\
                                                 gl_Position =   u_Matrix * a_Position;\n\
                                             }";
    const char * fragmentShaderResourceStr= "precision mediump float;\n\
                                             uniform sampler2D _texture0;\n\
                                             uniform sampler2D _texture1;\n\
                                             uniform float     _mix;\n\
                                             varying vec2      out_uv;\n\
                                             void main()\n\
                                             {\n\
                                                 vec4 color0    =  texture2D(_texture0, out_uv);\n\
                                                 vec4 color1    =  texture2D(_texture1, out_uv);\n\
                                                 vec4 dstColor  =  color0 * (1.0 - _mix)  + color1 * _mix;\n\
                                                 gl_FragColor   =  mix(color0, color1, _mix);\n\
                                             }";

    //                                           gl_FragColor   =   dstColor;
    programId = ShaderHelper::buildProgram(vertexShaderResourceStr, fragmentShaderResourceStr);

    uMatrixLocation     = glGetUniformLocation(programId, "u_Matrix");
    aPositionLocation   = glGetAttribLocation(programId, "a_Position");
    uMixLocation        = glGetUniformLocation(programId, "_mix");
    aTexUvLocation      = glGetAttribLocation(programId, "a_uv");
    uTextureUnit0       = glGetUniformLocation(programId, "_texture0");
    uTextureUnit1       = glGetUniformLocation(programId, "_texture1");
}

void GPUMixShaderProgram::setMVPUniforms(float* matrix){
    glUniformMatrix4fv(uMatrixLocation, 1, GL_FALSE, matrix);
}

void GPUMixShaderProgram::setMixUniform(double mix){
    glUniform1f(uMixLocation, static_cast<GLfloat>(mix));
}

呼び出しプロセスは次のとおりです。

void NativeGLRender::renderOnDraw(double elpasedInMilliSec)
{
    mWindowSurface->makeCurrent();
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    // GPUMixShaderProgram和GPUFlatSlidingProgram所需
    double _hasElasped = elpasedInMilliSec/1000 * 0.1f;
    if (_hasElasped > 1.0f)
    {
        _hasElasped = 1.0f;
    }
    gpuMixShaderProgram->ShaderProgram::userProgram();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_0_id);
    glUniform1i(gpuMixShaderProgram->uTextureUnit0, 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture_1_id);
    glUniform1i(gpuMixShaderProgram->uTextureUnit1, 1);

    CELL::Matrix::multiplyMM(modelViewProjectionMatrix, viewProjectionMatrix, cube->modelMatrix);
    gpuMixShaderProgram->setMVPUniforms(modelViewProjectionMatrix);
    gpuMixShaderProgram->setMixUniform(_hasElasped); // 设置混合因子
    cube->bindData(gpuFlatSlidingProgram);
    cube->draw();
    mWindowSurface->swapBuffers();
}

今回のシェーダープログラムの機能処理は、フラグメントシェーダーに焦点を当てています。頂点シェーダーは、関連データをフラグメントシェーダーに透過的に送信するだけです。実際、効果は最初の画像から2番目のターゲット画像に徐々に変化することです。ミキシングファクター_mixは、OpenGL.APIを介して時間の経過とともにシェーダープログラムに渡されます。

精度mediumpfloat;
ユニフォームサンプラー2D_texture0;
ユニフォームサンプラー2D_texture1;
ユニフォームフロート_mix;
可変vec2out_uv;
void main()
{     vec4 color0 = texture2D(_texture0、out_uv); //テクスチャ1に対応するカラーポイントのカラー値を抽出     vec4color1 = texture2D (_texture1、out_uv); //テクスチャ2に対応するカラーリングポイントのカラー値     vec4を抽出しますdstColor = color0 *(1.0-_mix)+ color1 * _mix; //     混合の数学計算を行いますgl_FragColor = mix(color0、color1、_mix) ; //混合計算にシステム独自の混合関数を使用する}




次に、ミックス関数のソースコードを自分で作成しました。これは、メインカーネル関数の3行目のコードです。ここでは少し理解しているようですが、すべてを理解しているわけではないようです。追加したいのは、組み込み関数texture2Dがテクスチャ座標out_uvに従って線形にサンプリングされることです。テクスチャ座標ポイントは4つしかありませんが、ラスター化後のサンプリングポイントは、実際にはシェーディングポイントの数と同じです。この例では、この文を説明できない場合があります。理解していなくてもかまいません。引き続き2番目の例を見てみましょう。

 

        シェーダープログラムに対応する2番目のレンダリング例

#include "GPUFlatSlidingProgram.h"
#include "ShaderHelper.h"

GPUFlatSlidingProgram::GPUFlatSlidingProgram()
{
    const char * vertexShaderResourceStr  = "uniform mat4    u_Matrix;\n\
                                             attribute vec4  a_Position;\n\
                                             attribute vec2  a_uv;\n\
                                             varying vec2    out_uv;\n\
                                             void main()\n\
                                             {\n\
                                                 out_uv      =   a_uv;\n\
                                                 gl_Position =   u_Matrix * a_Position;\n\
                                             }";

    const char * fragmentShaderResourceStr= "precision mediump float;\n\
                                             uniform sampler2D _texture0;\n\
                                             uniform sampler2D _texture1;\n\
                                             uniform float     offset;\n\
                                             varying vec2      out_uv;\n\
                                             void main()\n\
                                             {\n\
                                                 vec4 color = vec4(0,0,0,1);\n\
                                                 if(out_uv.x <= offset )\n\
                                                    color = texture2D(_texture1, vec2(out_uv.x + (1.0 - offset), out_uv.y));\n\
                                                 else\n\
                                                    color = texture2D(_texture0, vec2(out_uv.x - offset, out_uv.y));\n\
                                                 gl_FragColor   =  color; \n\
                                             }";

    programId = ShaderHelper::buildProgram(vertexShaderResourceStr, fragmentShaderResourceStr);

    uMatrixLocation     = glGetUniformLocation(programId, "u_Matrix");
    aPositionLocation   = glGetAttribLocation(programId,  "a_Position");
    aTexUvLocation      = glGetAttribLocation(programId,  "a_uv");
    uOffset             = glGetUniformLocation(programId, "offset");
    uTextureUnit0       = glGetUniformLocation(programId, "_texture0");
    uTextureUnit1       = glGetUniformLocation(programId, "_texture1");
}

void GPUFlatSlidingProgram::setMVPUniforms(float* matrix){
    glUniformMatrix4fv(uMatrixLocation, 1, GL_FALSE, matrix);
}

void GPUFlatSlidingProgram::setOffsetUniform(double offset){
    glUniform1f(uOffset, static_cast<GLfloat>(offset));
}

呼び出しプロセスは上記と同じですが、ミキシングファクター_mixが設定されていない点が異なります。今回は、タイムオフセットオフセットです。フラグメントシェーダーの分析に引き続き焦点を当てます。

精密ミディアムフロート;
均一なsampler2D_texture0;
均一なsampler2D_texture1;
均一なフロートオフセット。
さまざまなvec2out_uv;
void main()
{     vec4 color = vec4(0,0,0,1);     if(out_uv.x <=オフセット){        color = texture2D(_texture1、vec2(out_uv.x +(1.0-オフセット)、out_uv.y));     } else {        color = texture2D(_texture0、vec2(out_uv.x-オフセット、out_uv.y));     }     gl_FragColor = color; }







オフセットは0から1に徐々に変化し、テクスチャの横軸が判断に使用されます。オフセットの左側の表示スペースで、サンプリング用にtexture1の0〜out_uv.x +(1.0-オフセット)領域を抽出します。オフセットの右側にあります。スペースを表示し、サンプリングのためにtexture0の0〜out_uv.xオフセット領域を抽出します。理解していなくても構いません。下の簡単な図をご覧ください。

offset = 0.4の場合、最初にディスプレイの右側の領域を見てください。0.4(0.5〜6〜7〜8〜9〜1.0)より大きいすべてのテクスチャ座標は、最初にoffset =(0.1〜2〜3〜4〜の値を差し引きます。 5)次に、テクスチャtexture0のカラーポイントをサンプリングします。offset= 0.5の場合、テクスチャ座標は1桁(0.1〜2〜3〜0.4)減少し、texture0の表示領域は左に縮小し、視覚効果は右にシフトします。

オフセット= 0.4の場合、ディスプレイの左側の領域(uv.x <= offset)で、0.4未満のすべてのテクスチャ座標(0〜0.1〜0.2〜0.3〜0.4)は、画像のテクスチャ範囲全体ですべて+1になり、変化します(1〜1.1〜1.2〜1.3〜1.4)になり、0.4 =(0.6〜7〜8〜9〜1.0)を引いて、最後にこの座標のセットでtexture1のカラー値をサンプリングします。offset = 0.5の場合、テクスチャ座標にもう1桁追加します(0〜0.1〜0.2〜0.3〜0.4〜0.5)=>(1〜1.1〜1.2〜1.3〜1.4〜1.5)=>(0.5〜6〜7〜8 〜9〜1.0)。Texture1は境界を基準としており、左に向かって連続的に拡大します。

この例を通して、クラスメートがまだ目がくらんでいない場合は、並列コンピューティングの基本概念を習得したことを祝福します。これは2レベルの並列処理です。フラグメントシェーダーはシェーディングポイントの単位で実行され、ハードウェアのGPUレンダリングを1つずつシェーディングできないため、フラグメントシェーダーの書き込みには、基本的に、NIVIDAのCUDAパラレルでのパラレル思考が必要です。算術ライブラリの主要なカーネル関数は、実際にはフラグメントシェーダープログラムと同等です。興味のある学生は、BaiduCUDAで視野を広げることができます。

2つの例を通して、フラグメントカラーリングプログラムのコーディング標準といくつかのアプリケーションスキルを学び、よく理解されているいくつかの概念を導き出しました。

おすすめ

転載: blog.csdn.net/a360940265a/article/details/89083798