Opengl Fixed Function Pipeline или как перенести освещение в шейдер

Версия Minecraft
1.7.10
1,869
52
347
Всем привет.
Захотел я тут добавить некоторые спецэффекты предмету(в руке от первого лица), но для их обработки необходима шейдерная программа.
Все бы ничего, да только если использовать шейдер, а не стандартный конвейер Fixed Function Pipeline, освещение очевидно нужно каким-то образом накладывать вручную.
Немного поискав, я пришел к выводу, что наложение текстурки лайтмапы не решит данную проблему:
Код:
#version 120
//...
in vec2 texCoord;
in vec2 lightMapTextureCoords;

uniform sampler2D originalTexture;
uniform sampler2D lightmap;

void main(void) {
    //...
    vec4 lightMap = texture2D(lightmap, lightMapTextureCoords / 240.0);
    gl_FragColor = objectTexture * lightMap;
}
Код:
#version 120
//...
varying vec2 texCoord;
varying vec2 lightMapTextureCoords;

void main(){
    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
    texCoord = vec2(gl_MultiTexCoord0);
    lightMapTextureCoords = vec2(gl_MultiTexCoord1);//получаем uv из текстурного юнита 1(юнит лайтмапы)
}
Днем мой предмет все равно темный, как ночью. Но если подойти к источнику света - все становится нормально.
Это наверное потому что текстурная координата лайтмапы v в любое время суток под открытом небом равна 240.
А если зайти куда-нибудь под навес, то все опять становится нормально.
Как исправить, думаю банальным домножением итогого цвета на временя суток дело не решится?

Мне кажется ответ тут более глобальный - каким-нибудь образом надо перенести стандартный пайплайн обработки в шейдер(хотя бы небольшую часть с освещением).
Ибо помимо лайтмапы в майнкрафте(как оказывается??) есть еще диффузное освещение, благодаря которому мы можем видеть темные области со стороны, обратной источнику света(по крайней мере так должно быть):
1544724587868.png
Само по себе такое довольно примитивное на первый взгляд освещение можно написать без особых усилий.
Но что использовать на источники света? близлежайшие блоки света? или можно обойтись встроенными glsl'овскими переменными?

gl_FrontLightModelProduct, gl_LightModel и gl_LightSource возвращают вообще непонятно что, видать это фейковое освещение блоках в иконках слотов
 
Решение
Про освещение от неба: у меня всё решалось без всяких костылей со "временем суток", я просто домножал цвет пикселя на цвет лайтмапы по нужным координатам. Возможно у тебя кривые координаты, возможно текстура не обновляется (день\ночь в майне...
1,990
18
104
Про освещение от неба: у меня всё решалось без всяких костылей со "временем суток", я просто домножал цвет пикселя на цвет лайтмапы по нужным координатам. Возможно у тебя кривые координаты, возможно текстура не обновляется (день\ночь в майне меняют _текстуру_ лайтмапы, для освещения от неба).

Вторичное освещение в майне довольно простое, там два источника света, их характеристики задаются через через glLight (в классе RenderHelper).

У меня получалось его симулировать подобным кодом в вершинном шейдере:
C++:
#if LIGHTING
    out vec4 diff;

    void PointLight(in int i, in vec3 eye, in vec3 normal, inout vec4 diffuse){
        vec3 VP = vec3(gl_LightSource[i].position);
        diffuse += max(0.0, dot(normal, VP));
    }
#endif

... <main>
#if LIGHTING
    vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
    vec3 eye = vec3(0.0, 0.0, 1.0);
    vec4 diffuse = vec4(0.0);
    PointLight(0, eye, normal, diffuse);
    PointLight(1, eye, normal, diffuse);
    diff = min(diffuse, vec4(1.0));
#endif

И таким во фрагментном (тут не только диффузное освещение, есть ещё и ambient):
C++:
vec4 pixel = texture2D(tex, textureCoord);
pixel.xyz *= texture2D(lightMap, lightCoord).xyz;
pixel = pixel * vertexColor;
#if LIGHTING
    // simulates vanilla lighting
    pixel.rgb = (0.4 + diff.xyz * 0.6) * pixel.rgb;
#endif

Позиция источников света берется из встроенных gl_LightSource, так что наверняка надо вызывать enableStandardItemLighting, как это происходит в обычном сценарии отрисовки.

P.S. Код шейдеров не причесанный и там есть лишние куски кода, но думаю в данном случае это не очень важно :p
 
1,990
18
104
Ах да, текстурные координаты для лайтмапы у меня вычисляются таким образом (понятия не имею как я пришел к такому коду, но он родился после того как я заглянул в трансформации текстурной матрицы в EntityRenderer#enableLightmap. Освещение работает точь-в-точь как в ванильном майне, проверено)
C++:
lightCoord = (gl_MultiTexCoord1.st + vec2(8.0)) / 256.0;
 
Сверху