Venho armando meu mecanismo com código de verificação de erro. Vou tentar descrever essa situação com minhas melhores habilidades. Sempre que carrego um sombreador e há um erro (arquivo não existe, erro de compilação, qualquer coisa que possa dar errado) eu excluo o sombreador e defino o ponteiro como 0 (não consigo pensar em outra maneira de garantir que não tente anexar ou excluir lixo por acidente). Não quero interromper o programa se isso acontecer, porque alguém pode excluir ou modificar um único arquivo por acidente na pasta do jogo e não deseja tornar o jogo inteiro inutilizável por causa disso.
Agora, o problema é que existe um comportamento padrão na situação em que anexo shaders a um programa que tem o ponteiro igual a 0?
No meu programa, se eu anexar um shader de vértice igual a 0 e um shader de fragmento igual a 0, o OpenGL usará o programa padrão (exibirá tudo em branco):
Este é um cubo girado cujas dimensões já estão no espaço do clipe, renderizadas sem projeção em perspectiva ou verificação de profundidade. É carregado de um arquivo .obj.
Agora, se eu anexar um shader de fragmento adequado, mas o shader de vértice será 0, recebo o seguinte:
Qual é o que eu esperaria, tudo que o shader de fragmento faz é gerar um vec4 (1.0, 0.3, 0.7, 1.0), não há shader de vértice, então o OpenGL usa o padrão (essa é uma suposição correta?).
Agora, no entanto, se eu anexar um shader de vértice correto, mas anexar um shader de fragmento igual a 0 (ou não anexarei nenhum shader de fragmento), vou receber essa bagunça:
Algo que você não pode ver é que esse modelo está sendo pintado de cores diferentes, então, na minha tela, parece uma viagem ácida com linhas horizontais pretas.
Estou um pouco confuso, porque eu esperaria que o cubo fosse apenas branco. Gostaria de ressaltar que meu código de sombreador é simples, não estou trocando nenhuma variável entre sombreadores de vértice e fragmentos. Verificando se o ponteiro não é igual a 0 não muda nada, o programa vinculado age da mesma forma que se eu desse um ponteiro igual a 0. O mais estranho para mim é que ele sempre está bem sombreado, não é apenas lixo.
EDIT: Talvez o shader de fragmento padrão espera um valor gl_ do vértice que eu estou omitindo para definir? Isso meio que explica por que a superfície é bem sombreada, o sombreador de fragmento espera uma entrada suave, mas esse valor é apenas lixo, porque eu não o defini.
Agora, esse é um "comportamento indefinido" ou é assim que é suposto funcionar?
Respostas:
Verifique a seção 2.11 da especificação OpenGL 4.2 :
Esse é um "comportamento indefinido" que age de maneira diferente por implementação.
Quanto à solução para não conseguir encontrar um sombreador, achei melhor codificar um sombreador de vértice e um fragmento e carregá-los antes de qualquer outra coisa e usá-lo no lugar de qualquer sombreador ausente. Dessa forma, muitos dos uniformes que eu defino (matrizes de transformação) ainda serão aprovados e o resultado parecerá meio decente. Por exemplo, aqui está como eu faço isso (C #):
Também codificar uma textura padrão é uma boa idéia.
fonte
glShaderSource
preciso um conjunto de strings.#ifdef
. É não há de modo que você pode enviar cada linha como uma string separada. Sim, funciona, mas é um estilo de codificação horrível. É como criar um arquivo .cpp #incluindo cada linha individualmente . Sim, ele será compilado, mas não é assim que você usa #include.