USD对程序纹理支持的研究


  • 网站研运

    大家好,又有一段时间没有发布文章了。这次还是介绍最近研究USD的一些内容。主要是USD针对程序纹理的支持。如果有时间的话,还会给大家分享更多有关USD的内容的。

    首先皮克斯工作室推出的USD文档以及一些示例代码并没有介绍程序化纹理的内容。但是有一些爱好者将自己输出的USD文档分享出来,其中包括了卡通着色的内容。下面就是一个简单的USD内容,它可以显示卡通着色(本例在USD 19.07中测试):

    cellshaded.usd

    #usda 1.0
    
    
    def Scope "Materials" {
    
        def Material "CelMaterial" { 
    
            rel displayLook:bxdf = </Materials/CelShader>
    
        }
    
        def Shader "CelShader" {
    
            uniform asset info:filename = @celshader.glslfx@
            
        }
    
    }
    
    def Scope "Geom" {
    
        def Mesh "Subdiv" {
    
            rel material:binding = </Materials/CelMaterial>
    
            float3[] extent = [(-1.21273, -1.21273, -1.21273), (1.21273, 1.21273, 1.21273)]
    
            color3f[] primvars:displayColor = [(0.078431372549019607, 0.51372549019607838, 0.80784313725490198)]
    
            int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
    
            int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, 1, 7, 5, 3, 6, 0, 2, 4]
    
            point3f[] points = [(-1.21273, -1.21273, -1.21273), (1.21273, -1.21273, -1.21273), (-1.21273, -1.21273, 1.21273), (1.21273, -1.21273, 1.21273), (-1.21273, 1.21273, 1.21273), (1.21273, 1.21273, 1.21273), (-1.21273, 1.21273, -1.21273), (1.21273, 1.21273, -1.21273)]
    
            
        }
    }
    

    cellshader.glslfx

    -- glslfx version 0.1
    
    -- configuration
    {
        "techniques" : {
            "default" : {
                "surfaceShader" : {
                    "source": [ "Cel.SurfaceShader" ]
                }
            }
        }
    }
    
    -- glsl Cel.SurfaceShader
    
    vec4 
    surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord)
    {
        float c = 0.0;
    
        // Hard-code the light direction for now
        vec3 l = vec3(0.0, 0.0, 1.0);
        vec3 n = normalize(Neye);
    
        c = dot(l, n);
    
        vec3 cl;
    
        if (c > 0.99)
            cl = vec3(1.0, 1.0, 1.0);
        else if (c > 0.9)
            cl = color.xyz;
        else if (c > 0.5)
            cl = color.xyz*0.75;
        else if (c > 0.25)
            cl = color.xyz*0.50;
        else 
            cl = color.xyz*0.25;
    
        return vec4(cl, color.w);
    }
    

    效果如下(右键另存图片,使用7z文件文档管理器可以解压获得源代码)
    1_7z.png

    我在这个例子的基础上加以发挥,想出了一个办法可以支持在纹理立方体上贴棋盘格图。整个着色器是使用GLSL做的。其中棋盘格的GLSL代码是我从“萌梦动作编辑器”中的时间轴例子借鉴的。

    7_29_1.usda

    #usda 1.0
    (
        defaultPrim = "cube"
        endTimeCode = 1
        startTimeCode = 1
        upAxis = "Y"
    )
    
    def Mesh "cube"
    {
        uniform bool doubleSided = 1
        float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)]
        int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
        int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, 1, 7, 5, 3, 6, 0, 2, 4]
        normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0)] (
            interpolation = "faceVarying"
        )
        point3f[] points = [(-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5)]
        float2[] primvars:st = [(0.375, 0), (0.625, 0), (0.625, 0.25), (0.375, 0.25), (0.625, 0.5), (0.375, 0.5), (0.625, 0.75), (0.375, 0.75), (0.625, 1), (0.375, 1), (0.875, 0), (0.875, 0.25), (0.125, 0), (0.125, 0.25)] (
            interpolation = "faceVarying"
        )
        int[] primvars:st:indices = [0, 1, 2, 3, 3, 2, 4, 5, 5, 4, 6, 7, 7, 6, 8, 9, 1, 10, 11, 2, 12, 0, 3, 13]
        uniform token subdivisionScheme = "none"
    
        rel material:binding = </cube/material>
        
        def Material "material"
        {
            token outputs:surface.connect = </cube/material/outputShader.outputs:surface>
    
            def Shader "PBRShader"
            {
                uniform token info:id = "UsdPreviewSurface"
                color3f inputs:diffuseColor = ( 1, 0, 0 )
                float inputs:metallic = 0
                float inputs:roughness = 0.4
                float inputs:opacity = 1
                //float inputs:ior = 0.1
                float inputs:clearcoat = 0.6
                float inputs:clearcoatRoughness = 1
                color4f outputs:color
            }
    
            def Shader "outputShader"
            {
                uniform asset info:filename = @./7_29_1.glslfx@
                color4f baseColor.connect = </cube/material/texture.outputs:color>
                color4f outputs:color
            }
    
            def Shader "texCoordReader"
            {
                uniform token info:id = "HwPrimvar_1"
                uniform token info:varname = "st"
                float2 outputs:result
            }
    
            def Shader "texture" 
            {
                uniform token info:id = "HwUvTexture_1"
                float2 uv.connect = </cube/material/texCoordReader.outputs:result>
                uniform asset info:filename = @./7_29_1.jpg@
                color4f outputs:color
            }
        }
    }
    

    7_29_1.glslfx

    -- glslfx version 0.1
    
    #import $TOOLS/glf/shaders/simpleLighting.glslfx
    
    -- configuration
    {
        "techniques": {
            "default": {
                "surfaceShader": {
                    "source": [ "test.Surface" ]
                }
            }
        }
    }
    
    -- glsl test.Surface
    
    float Mod( int x, int y )
    {
        return float( x ) - float( x / y ) * float( y );
    }
    vec4 checkerBoard( float opacity )
    {
        float gridWidth = 4.0;
        float gridHeight = 4.0;
        float width = 160.0;
        float height = 160.0;
        vec2 uv = HdGet_st().xy;
        float mod2X = Mod( int( width * uv.x / gridWidth ), 2 );
        float mod2Y = Mod( int( height * uv.y / gridHeight + 0.5 ), 2 );
        vec4 barColor = vec4( 1.0 );
        if ( mod2X == 1.0 && mod2Y == 0.0 ||
             mod2X == 0.0 && mod2Y == 1.0 )
        {
            barColor = vec4( 0.0, 0.0, 0.0, opacity );
        }
        else
        {
            barColor = vec4( 1.0, 1.0, 1.0, opacity );
        }
        return barColor;
    }
    
    vec4 surfaceShader( vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord )
    {
        vec4 result = checkerBoard( 0.3 );
    #if defined( HD_HAS_baseColor )
        result += HdGet_baseColor( );
    #endif
    #if defined( HD_HAS_selColor )
        result *= HdGet_selColor( );
    #endif
        return result;
    }
    

    2_7z.png
    (右键另存图片,使用7z文件文档管理器可以解压获得源代码)

    要说GLSLFX和GLSL的不同,我这边研究了一下,应该是GLSLFX是皮克斯工作室的USD项目在大实现Hydra的过程中自己研发了一个处理着色网络的格式。它对GLSL做了浅层的封装,并且定义了自己的渲染流程(渲染管线)。我们翻阅USD的源码,可以找到文件名带有.glslfx后缀的文件,通常包含了vertexShaderdisplacementShadergeometryShadersurfaceShaderfragmentShadercomputeShader等等。最终还是输出渲染API能够辨认的GLSL代码的。我们可以通过设置HDST_DUMP_SHADER_SOURCEFILE环境变量将生成后的着色器输出到文件中以便排错(在USD 19.07之前没有此宏)。


Log in to reply
 

走马观花

最近的回复

  • 诶 没有Linux吗??

    read more
  • 萌梦 男孩,女孩,和蛋

    menghome.png

    read more
  • 设计模式-工厂模式

    使用qt/qml来演示设计模式效果,便于学习理解

    1)定义创建对象的接口,封装对象的创建
    2)使具体化类的工作延迟到工厂子类中

    bg.png
    image.png

    1. 工厂类

    createProduct使用了参数来选择要创建哪个产品

    #ifndef FACTORY_H #define FACTORY_H #include <QObject> class Product; class QString; class Factory: public QObject { Q_OBJECT public: virtual ~Factory() = 0; virtual Product* createProduct(QString type) = 0; protected: Factory(); }; class ConcreteFactory: public Factory { Q_OBJECT public: ~ConcreteFactory(); ConcreteFactory(); public slots: Product* createProduct(QString type); }; #endif // FACTORY_H #include "factory.h" #include "product.h" #include <QtQml/qqml.h> Factory::~Factory() { } Factory::Factory() { qmlRegisterType<Product>("Product", 1, 0, "Product"); } ConcreteFactory::~ConcreteFactory() { } ConcreteFactory::ConcreteFactory() { } Product *ConcreteFactory::createProduct(QString type) { if(type == "boy") return static_cast<Product *>(new ConcreteProduct1()); else if(type == "girl") return static_cast<Product *>(new ConcreteProduct2()); return static_cast<Product *>(new ConcreteProduct1()); } 2 产品类

    一个产品是萌梦男,一个产品是萌梦女

    #ifndef PRODUCT_H #define PRODUCT_H #include <QObject> class Product: public QObject { Q_OBJECT public: virtual ~Product() = 0; Q_PROPERTY(QString icon READ icon NOTIFY iconChanged) QString m_icon; QString icon() const { return m_icon; } signals: void iconChanged(QString icon); protected: Product(); signals: public slots: }; class ConcreteProduct1: public Product { Q_OBJECT public: ~ConcreteProduct1(); ConcreteProduct1(); }; class ConcreteProduct2: public Product { Q_OBJECT public: ~ConcreteProduct2(); ConcreteProduct2(); }; #endif // PRODUCT_H #include "product.h" Product::~Product() { } Product::Product() { } ConcreteProduct1::~ConcreteProduct1() { } ConcreteProduct1::ConcreteProduct1() { m_icon = "qrc:/images/boy.png"; } ConcreteProduct2::~ConcreteProduct2() { } ConcreteProduct2::ConcreteProduct2() { m_icon = "qrc:/images/girl.png"; } 3. main.qml

    使用timer,canvas,listview等实现一个自动化生产的动画效果

    源代码

    Fork me on Gitee

    read more
  • blender建模 章鱼
    捕获2.PNG 😵

    read more

关注我们

微博
QQ群