Семантика CG-шейдеров в OpenGL 3.x? - PullRequest
2 голосов
/ 03 сентября 2011

Раньше у меня были CG-шейдеры, работающие с массивами вершин в OpenGL 2.x, но я обновил использование VBO и VAO в OpenGL 3.x, и теперь семантика, похоже, не работает, за исключением POSITION.CG не выдает никаких ошибок компиляции, но если я установлю свой выходной цвет в своем фрагментном шейдере на свое входное нормальное значение, я просто получу сплошной черный.Есть другой ответ, который ссылается на страницу, в которой говорится, что нужно использовать cgGLEnableClientState (которая сама по себе ничего не сделала) и cgGLSetParameterPointer (что кажется сумасшедшим, поскольку я уже отправляю данные в OpenGL, зачем отправлять еще одну копию через CG).Так что же мне не хватает?

Вершинный шейдер:

struct input
{
    in uniform float4x4 worldViewProjMatrix;
    in uniform float4x4 invTransWorldMatrix;
    in uniform float4x4 worldMatrix;
    in uniform float3 lightDir;
    in uniform float3 eyePosition;
    in varying float4 position : POSITION;
    in varying float4 normal : NORMAL;
    in varying float2 texCoord : TEXCOORD;
};

struct output
{
    out varying float4 position : POSITION;
    out varying float2 texCoord : TEXCOORD0;
    out varying float3 light : TEXCOORD1;
    out varying float3 normal : TEXCOORD2;
    out varying float3 view : TEXCOORD3;
};

output main(input IN)
{
    output OUT = output(0);
    OUT.position = mul(IN.worldViewProjMatrix, IN.position);

    OUT.texCoord = IN.texCoord;

    OUT.light = IN.lightDir;

    float3 worldPosition = normalize(mul(IN.worldMatrix, IN.position)).xyz;
    OUT.view = IN.eyePosition - worldPosition;

    OUT.normal = normalize(mul(IN.invTransWorldMatrix, IN.normal)).xyz;

    return OUT;
}

Фрагментный шейдер:

struct input {
    in varying float2 texCoord : TEXCOORD0;
    in varying float3 light : TEXCOORD1;
    in varying float3 normal : TEXCOORD2;
    in varying float3 view : TEXCOORD3;
    in uniform float3 diffuse;
    in uniform float3 ambient;
    in uniform float3 specular;
    in uniform float shininess;
    in uniform sampler2D colorMapSampler;
};

float4 main(input IN) : COLOR
{
    float4 color = tex2D(IN.colorMapSampler, IN.texCoord);
    float3 normal = normalize(IN.normal);
    float3 lightDir = normalize(IN.light);
    float3 viewDir = normalize(IN.view);
    float3 diff = saturate(dot(normal, lightDir));

    float3 reflect = normalize(2 * diff * normal - lightDir);
    float3 specular = pow(saturate(dot(reflect, viewDir)), IN.shininess);

    float4 result;
    //result = float4(color.rgb * (IN.ambient + IN.diffuse * diff) + IN.specular * specular, 1.0f);
    result = float4(IN.normal, 1.0f);
    return result;
}

Я нашел место, в котором они перечислены как индексы для glVertexAttribPointer,но они могут легко ошибаться (это Shader::POSITION, Shader::NORMAL и т. д. в функции настройки VBO):

enum GenericVertexInputIndices
{
    POSITION        = 0,
    BLENDWEIGHT     = 1,
    NORMAL          = 2,
    DIFFUSE         = 3,    COLOR0      = 3,
    SPECULAR        = 4,    COLOR1      = 4,
    TESSFACTOR      = 5,    FOGCOORD    = 5,
    PSIZE           = 6,
    BLENDINDICES    = 7,
    TEXCOORD0       = 8,
    TEXCOORD1       = 9,
    TEXCOORD2       = 10,
    TEXCOORD3       = 11,
    TEXCOORD4       = 12,
    TEXCOORD5       = 13,
    TEXCOORD6       = 14,   TANGENT     = 14,
    TEXCOORD7       = 15,   BINORMAL    = 15,
};

функция настройки VBO ниже:

void MeshObject::initVBO(const unsigned int&_indexVBO, unsigned int& _indexOffset)
{
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    //sub in this section of the index data
    m_indexOffset = _indexOffset;
    _indexOffset = _indexOffset + m_indices.size();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexVBO);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_indexOffset * sizeof(unsigned short), m_indices.size() * sizeof(unsigned short), &(m_indices[0]));

    //init vertex data
    glGenBuffers(1, &m_vertexVBO);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO);
    {
        glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(VertexData), &(m_data[0]), GL_STATIC_DRAW);

        glEnableVertexAttribArray(Shader::POSITION);
        glVertexAttribPointer(Shader::POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)0);
        glEnableVertexAttribArray(Shader::NORMAL);
        glVertexAttribPointer(Shader::NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)12);
        glEnableVertexAttribArray(Shader::TEXCOORD0);
        glVertexAttribPointer(Shader::TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)24);
    }
}

шейдерФункция привязки ниже:

void Shader::bind(const matrix4 &_worldTransform, const Material::MaterialInfo &_info)
{
    CGerror error;

    //bind to the shader
    CGprofile profile = renderGlobals.shaderMgr.getProfile(static_cast<Shader::ShaderType>(m_shaderType));
    cgGLEnableProfile(profile);
    error = cgGetError();
    cgGLBindProgram(m_program);
    error = cgGetError();

    switch (m_shaderType)
    {
        case VERTEX:
        {
            //get vertex parameters
            CGparameter worldMatrix = cgGetNamedParameter(m_program, "IN.worldMatrix");
            CGparameter worldViewProjMatrix = cgGetNamedParameter(m_program, "IN.worldViewProjMatrix");
            CGparameter invTransWorldMatrix = cgGetNamedParameter(m_program, "IN.invTransWorldMatrix");
            CGparameter light = cgGetNamedParameter(m_program, "IN.lightDir");
            CGparameter eyePosition = cgGetNamedParameter(m_program, "IN.eyePosition");
            error = cgGetError();

            //set vertex parameters
            matrix4 worldViewProj = *(renderGlobals.debugCamera.getViewProjectionMatrix()) * _worldTransform;
            cgGLSetMatrixParameterfc(worldViewProjMatrix, worldViewProj.m16);

            matrix4 invTransWorld = _worldTransform.getInverse().getTranspose();
            if (invTransWorldMatrix != NULL)
            {
                cgGLSetMatrixParameterfc(invTransWorldMatrix, invTransWorld.m16);
            }

            if (worldMatrix != NULL)
            {
                cgGLSetMatrixParameterfc(worldMatrix, _worldTransform.m16);
            }

            vector3 lightPos = *renderGlobals.debugCamera.getPosition();
            //vector3 lightPos = vector3(0.0f, 0.0f, 0.0f);
            vector3 lightDir = lightPos - _worldTransform.wAxis;
            if (light != NULL)
            {
                cgGLSetParameter3fv(light, lightDir.v);
            }
            if (eyePosition != NULL)
            {
                cgGLSetParameter3fv(eyePosition, renderGlobals.debugCamera.getPosition()->v);
            }
            error = cgGetError();
            break;
        }
        case FRAGMENT:
        {
            //set up material info
            CGparameter diffuse = cgGetNamedParameter(m_program, "IN.diffuse");
            CGparameter ambient = cgGetNamedParameter(m_program, "IN.ambient");
            CGparameter specular = cgGetNamedParameter(m_program, "IN.specular");
            CGparameter shininess = cgGetNamedParameter(m_program, "IN.shininess");

            if (diffuse != NULL)
            {
                cgGLSetParameter3fv(diffuse, _info.diffuse.rgb);
            }
            if (ambient != NULL)
            {
                cgGLSetParameter3fv(ambient, _info.ambient.rgb);
            }
            if (specular != NULL)
            {
                cgGLSetParameter3fv(specular, _info.specular.rgb);
            }
            if (shininess != NULL)
            {
                cgGLSetParameter1f(shininess, _info.shininess);
            }

            //set up textures
            CGparameter colorMapSampler = cgGetNamedParameter(m_program, "IN.colorMapSampler");
            if (colorMapSampler != NULL)
            {
                if (_info.textureInfo[0].size() > 0)
                {
                    Index<Texture> texture = _info.textureInfo[0][0].texture;
                    cgGLSetTextureParameter(colorMapSampler, texture->getID());

                    cgGLEnableTextureParameter(colorMapSampler);
                } else {
                    cgGLDisableTextureParameter(colorMapSampler);
                }
            }
            break;
        }
        default:
        {
            //ERROR: tryin to bind a shader with an unknown type
            assert(0);
            unbind();
            return;
        }
    }
}

1 Ответ

0 голосов
/ 04 сентября 2011

Изменил семантику в структуре ввода вершин, чтобы использовать ATTR *, совпадающий с тем, что есть в GenericVertexInputIndices и вуаля, все работает. Я пытался изменить всю свою семантику на ATTR * как в вершинном, так и фрагментном шейдерах раньше и получил кучу ошибок конфликта доменов, но не заметил, что он не жаловался на ошибки в структуре ввода вершин. По-видимому, они только для ввода вершин. Еще одна маленькая деталь, которая полностью все портит.

...