Раньше у меня были 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;
}
}
}