4

私と友人は、将来のゲームで使用するエディター (CAD のような) を開発しています。Qt フレームワークと OpenGL を使用しています。私たちが直面している問題は、nVidia カードが統合された彼のラップトップで、シェーディングが期待どおりに機能し、適切にレンダリングされることです。統合 ATI カードを搭載したラップトップと、Radeon HD5850 を搭載したデスクトップでは、フォン照明の動作が少し異なります。明るい点と暗い点が多くなり、見栄えがよくありません。また、トゥーン シェーダーを使用して、エッジの周りにシルエットを描画し、色の陰影の量を制限しています。

トゥーン シェーダーは 2 パス レンダリングを使用します。最初のパスではオブジェクトを元のサイズよりもわずかに大きい黒でレンダリングし (各頂点を法線方向にわずかにシフト)、シルエットを作成し、次に 2 番目のパスでオブジェクトを通常どおりにレンダリングします (シェード スペクトルを制限するだけです)。 、よりコミックのように見えます)。

画像は、2台のコンピューターで同じものです。上記の最初の違いは、2 つ目は、友人のコンピューターではシルエットが引き伸ばされているため、オブジェクトの周りに均一なシルエットが作成されますが、コンピューターではわずかに上に移動され、上に太い線が作成されることです。上と下に線はありません。

もう 1 つはフォン ライティングで、オブジェクトが編集されるキューブを照らします。繰り返しになりますが、友人のコンピューターではうまくレンダリングされますが、私のコンピューターではほとんどすべて黒またはすべて白です。

最初の画像 (nVidia カード):

  モンキー1

2 番目の画像 (ATI カード):

  モンキー2

コードが長く、シェーダーではなく Qt の設定に問題がある可能性があることは理解していますが、悪い習慣だと思うものがあれば回答してください。

フォン シェーディングのコードは次のとおりです。

    #version 400

    in vec4 aVertex;
    in vec4 aNormal;
    in vec2 aTexCoord;

    uniform mat4 uPVM;
    uniform mat4 uViewModel;
    uniform mat4 uNormal;
    uniform int  uLightsOn;

    out vec2 vTexCoord;
    out vec3 vNormal;
    flat out vec3 mEye;
    flat out vec3 mLightDirection;

    flat out vec4 mAxisColor;

    void main(void)
    {
        if(uLightsOn == 1) {
            mEye = (uViewModel * aVertex).xyz;
            mLightDirection = vec4(2.0,-2.0,1.0,0.0).xyz;
            vNormal = (uNormal * aNormal).xyz;
        }

        gl_Position = uPVM * aVertex;
        vTexCoord = aTexCoord;
        mAxisColor = aNormal;
    }

フォン フラグメント シェーダー:

    #version 400

    uniform sampler2D uTexture0;
    uniform int  uLightsOn;
    uniform vec3 uHighlightColor;
    uniform int uTextured;
    uniform int uAxisRender;

    in vec2 vTexCoord;
    in vec3 vNormal;
    flat in vec3 mEye;
    flat in vec3 mLightDirection;

    out vec4 fragColor;

    flat in vec4 mAxisColor;

    struct TMaterial {
        vec4 diffuse;
        vec4 ambient;
        vec4 specular;
        float shininess;
    };

    TMaterial material;

    void setup() {
        // setupMaterials

        material.ambient = vec4(0.4);
        material.diffuse = vec4(0.9);
        material.specular = vec4(0.0);
        material.shininess = 0.3;

    }

    void main(void)
    {
        setup();

        vec3 finalHighlightColor = uHighlightColor;

        if(finalHighlightColor.x <= 0.0) finalHighlightColor.x = 0.1;
        if(finalHighlightColor.y <= 0.0) finalHighlightColor.y = 0.1;
        if(finalHighlightColor.z <= 0.0) finalHighlightColor.z = 0.1;

        if(uLightsOn == 0) {
            if(uAxisRender == 1) fragColor = mAxisColor;
            else fragColor = vec4(finalHighlightColor,1.0);
            return;
        }

        vec4 diffuse;
        vec4 spec = vec4(0.0);
        vec4 ambient;

        vec3 L = normalize(mLightDirection - mEye);
        vec3 E = normalize(-mEye);
        vec3 R = normalize(reflect(-L,vNormal));

        ambient = material.ambient;

        float intens = max(dot(vNormal,L), 0.0);

        diffuse = clamp( material.diffuse * intens  , 0.0, 1.0 );
        if(intens > 0.0) spec = clamp ( material.specular * pow(max(dot(R,E),0.0),material.shininess) , 0.0, 1.0 );

        if(uTextured == 1) fragColor = (ambient + diffuse + spec) * texture(uTexture0,vTexCoord);
        else fragColor = (ambient + diffuse + spec) * vec4(finalHighlightColor,1.0);

    }

そしてトゥーンシェーダー:

    #version 400

    in vec4 aVertex;
    in vec4 aNormal;
    in vec2 aTexCoord;

    uniform mat4 uPV;
    uniform mat4 uM;
    uniform mat4 uN;
    uniform vec3 uLightPosition;
    uniform vec3 uCameraPosition;
    uniform int  uSilhouetteMode;
    uniform float uOffset;
    // if this uniform is passed, all the toon rendering is going off and only simple axis are rendered
    // last data in aNormal are colors of those axis if everything was ser properly.
    uniform int  uAxisRendering;
    flat out vec4 fAxisColor;

    out vec4 vNormal;
    out vec2 vTexCoord;
    out vec3 vDirectionToCamera;
    out vec3 vDirectionToLight;


    void silhouetteMode() {
        gl_Position = uPV * uM * vec4(aVertex.xyz + aNormal.xyz * uOffset,1.0f);
    }

    void toonMode() {
        vec4 worldPosition = uM * aVertex;

        vDirectionToCamera = uCameraPosition - worldPosition.xyz;
        vDirectionToLight = uLightPosition - worldPosition.xyz;
        vNormal = uN * aNormal;

        gl_Position = uPV * worldPosition;
    }

    void axisMode() {
        fAxisColor = aNormal;

        gl_Position = uPV * uM * aVertex;
    }

    void main(void)
    {
        vTexCoord = aTexCoord;

        if(uSilhouetteMode == 1) {
            silhouetteMode();
        } else {
            if(uAxisRendering == 1) axisMode();
            else toonMode();
        }
    }

そしてフラグメントシェーダー

    #version 400

    uniform sampler2D uTexture;
    uniform vec3 uBaseColor;
    uniform float uNumShades;
    uniform int  uSilhouetteMode;

    uniform int  uAxisRendering;
    flat in vec4 fAxisColor;

    in vec4 vNormal;
    in vec2 vTexCoord;
    in vec3 vDirectionToCamera;
    in vec3 vDirectionToLight;

    out vec4 outFragColor;

    void main(void)
    {

        if(uSilhouetteMode == 1) {
            outFragColor = vec4(uBaseColor,1.0);
            return;
        }

        if(uAxisRendering == 1) {
            outFragColor = fAxisColor;
            return;
        }

        float l_ambient = 0.1;
        float l_diffuse = clamp(dot(vDirectionToLight,vNormal.xyz),0.0,1.0);
        float l_specular;
        vec3 halfVector = normalize(vDirectionToCamera + vDirectionToLight);

        if(dot(vDirectionToLight,vNormal.xyz) > 0.0) {
            l_specular = pow(clamp(dot(halfVector,vNormal.xyz),0.0,1.0),64.0);
        } else {
            l_specular = 0.0;
        }

        float intensity = l_ambient + l_diffuse + l_specular;
        float shadeIntesity = ceil(intensity * uNumShades)/ uNumShades;

        outFragColor = vec4(texture(uTexture,vTexCoord).xyz * shadeIntesity * uBaseColor,1.0);
    }

最後に、OpenGLWindow の初期化 (Qt で)

    OpenGLWindow::OpenGLWindow(QWindow *parent) :
        QWindow(parent),m_animating(false), m_initialized(false), m_animationTimer(NULL)
    {
        setSurfaceType(QWindow::OpenGLSurface);

        QSurfaceFormat format;
        format.setDepthBufferSize( 24 );
        format.setMajorVersion( 4 );
        format.setMinorVersion( 0 );
        format.setSamples( 4 );
        format.setProfile( QSurfaceFormat::CoreProfile );
        setFormat( format );
        create();

        if(!m_context) {
            m_context = new QOpenGLContext(this);
            m_context->setFormat(requestedFormat());
            m_context->create();
            m_context->makeCurrent(this);

            initializeOpenGLFunctions();
        }

        m_animationTimer = new QTimer(this);
        connect(m_animationTimer, SIGNAL(timeout()), this, SLOT(renderer()));
        m_animationTimer->setInterval(16);
    }
4

1 に答える 1