Disney的brdf项目框架分析

接着这篇文章:https://blog.csdn.net/wodownload2/article/details/104273629
我们继续。
1.如何加载brdf文件,brdf文件是里面是什么函数?
BRDFBase.cpp中:

bool BRDFBase::loadBRDF( const char* filename )
  1. BRDF文件所在位置:
    在这里插入图片描述

3.BRDF内容分析举例
以d_ggx.brdf为例子:

analytic

# ggx from Walter 07

# variables go here...
# only floats supported right now.
# [type] [name] [min val] [max val] [default val]

::begin parameters
float alpha 0.001 1 .1 //最小值,最大值,默认值
::end parameters


# Then comes the shader. This should be GLSL code
# that defines a function called BRDF (although you can
# add whatever else you want too, like sqr() below).

::begin shader
const float PI = 3.14159265358979323846;

float sqr(float x) { return x*x; }

float GGX(float alpha, float cosThetaM)
{
    float CosSquared = cosThetaM*cosThetaM;
    float TanSquared = (1-CosSquared)/CosSquared;
    return (1.0/PI) * sqr(alpha/(CosSquared * (alpha*alpha + TanSquared)));
}

vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
    vec3 H = normalize( L + V );
    float D = GGX(alpha, dot(N,H));
    return vec3(D);
}
::end shader

BRDF函数调用GGX函数。

读取的细细分析:

BRDFBase* b = NULL; //基类指针
bool success = false; //bool变量
// .brdf is an analytic BRDF file
else if( extension == "brdf" )
{
    b = new BRDFAnalytic;
    success = b->loadBRDF( filename.c_str() );
}

读取第一行:

std::ifstream ifs( filename );
std::string line, trimmedLine;
// first line needs to be the BRDF type
if( !getline( ifs, line ) )
    return false; 

判断读取的类型:

// make sure we know how to read this
std::string type = trim(line);
type = type.substr( 0, type.find( ' ' ) );
if( type != "analytic" && type != "bparam" )
    return false;

接下来是逐行读取:

while( getline( ifs, line ) )
{
    trimmedLine = line;
    trim( trimmedLine );

    // skip blank lines
    if( trimmedLine.length() == 0 )
        continue;
    // skip comments
    if( trimmedLine[0] == '#' )
          continue;

处理参数:

在这里插入图片描述

处理float的代码:

else if( token == "float" )
{
    std::string name;
    float min, max, value;

    os >> name;
    os >> min;
    os >> max;
    os >> value;

    addFloatParameter( name, min, max, value );
}

float类型的结构体:

struct brdfFloatParam
{
    std::string name;
    float minVal;
    float maxVal;
    float defaultVal;
    float currentVal;
};

实例化一个float结构体,然后添加到列表中去:

void BRDFBase::addFloatParameter( std::string name, float min, float max, float value )
{
    brdfFloatParam param;
    param.name = name;
    param.minVal = min;
    param.maxVal = max;
    param.defaultVal = value;
    param.currentVal = value;

    floatParameters.push_back( param );
    parameterTypes.push_back( BRDF_VAR_FLOAT );
}

参数读取完毕之后,就是一行一行读取shader,进行拼接:

bool BRDFAnalytic::processLineFromSection( std::string section, std::string line )
{
    if( section == "shader" )
        shader = shader + line + std::string("\n");
    else if( section == "isFunc" )
        isFunc = isFunc + line + std::string("\n");
	return true;
}

以画一个球体为例子:
LitSphereWidget类中的drawSphere方法:

准备shader:

void LitSphereWidget::drawSphere( double r, int lats, int longs )
{
    DGLShader* shader = NULL;

    // if there's a BRDF, the BRDF pbject sets up and enables the shader
    if( brdfs.size() )
    {
        shader = brdfs[0].brdf->getUpdatedShader( SHADER_LITSPHERE, &brdfs[0] );
        shader->setUniformMatrix4("projectionMatrix", glm::value_ptr(projectionMatrix));
        shader->setUniformMatrix4("modelViewMatrix",  glm::value_ptr(modelViewMatrix));
        shader->setUniformFloat( "incidentVector", incidentVector[0], incidentVector[1], incidentVector[2] );
        shader->setUniformFloat( "incidentTheta", inTheta );
        shader->setUniformFloat( "incidentPhi", inPhi );

        shader->setUniformFloat( "brightness", brightness );
        shader->setUniformFloat( "gamma", gamma );
        shader->setUniformFloat( "exposure", exposure );
        shader->setUniformFloat( "useNDotL", useNDotL ? 1.0 : 0.0 );
    }

这里的brdfs是一个集合,从集合中拿出第0个位置的brdf函数。

然后将读取出来的BRDF函数插入到指定的shader中去:getBRDFFunction就是获取brdf函数。

bool BRDFBase::compileShader( DGLShader*& shader, std::string vs, std::string fs, std::string gs )
{
    // nuke the shader if it exists
    if( shader )
        delete shader;

    // here's the tricky bit: load the shader templates, sticking in the BRDF function where needed
    std::string vertShader = loadShaderFromFile( vs, getBRDFFunction(), getISFunction() );
    std::string fragShader = loadShaderFromFile( fs, getBRDFFunction(), getISFunction() );

/*
    printf( "==========\n" );
    printf( "%s\n", fragShader.c_str() );
    printf( "==========\n" );
*/

    // try and compile it
    //IC: This expects file names!s
//	shader = new DGLShader( vertShader, fragShader );
    shader = new DGLShader();
    shader->setVertexShaderFromString(vertShader);
    shader->setFragmentShaderFromString(fragShader);
    if(!gs.empty())
        shader->setGeometryShaderFromFile(gs);
    shader->create();
    return shader->ready();
}

然后就是将shader塞到sphere中进行绘制,绘制的部分代码如下:

void Sphere::draw(const DGLShader *shader)
{
    if (!_ready) {
        init();
    }

    glf->glBindVertexArray(_vao);

    int vertex_loc = shader->getAttribLocation("vtx_position");
    if(vertex_loc>=0){
        glf->glBindBuffer(GL_ARRAY_BUFFER, _bufs[1]);
        glf->glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glf->glEnableVertexAttribArray(vertex_loc);
    }

    int color_loc = shader->getAttribLocation("vtx_color");
    if(color_loc>=0){
        glf->glBindBuffer(GL_ARRAY_BUFFER, _bufs[2]);
        glf->glVertexAttribPointer(color_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glf->glEnableVertexAttribArray(color_loc);
    }

ok,就有了:
在这里插入图片描述

发布了610 篇原创文章 · 获赞 96 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/wodownload2/article/details/104288758