Приветстсвую всех!
Пытаюсь воспроизвести древний пример 1996 года на opengl4
(чтобы рендерилась в точности картинка с использованием фиксированных функций - но до этого пока далеко).
Простенькая сцена.
Для простоты вывожу только три плоскости: пол, левую и правую стенки.
Последовательные запуски дают разные варианты затенения:
первый вариант
второй
третий
Сталкивался ли кто-нибудь с таким эффектом?
Чем он вызван?
В расчете модели освещения нет элементов случайности, так что в этом виноват не шейдер (вершинный/фрагментный).
Тут что-то с vbo?
Инициализация пола
void initFloor()
{
// 1) Текстура
GLfloat *textureData = make_texture(TEXDIM, TEXDIM);
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, TEXDIM, TEXDIM);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXDIM, TEXDIM, GL_RED, GL_FLOAT, textureData);
free(textureData);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR();
prog_set_uniform_int(&floorsh, "tex1", 0);
// 2) Геометрия
float vertexData[4*3]=
{
-100.f, -100.f, -320.f,
100.f, -100.f, -320.f,
100.f, -100.f, -640.f,
-100.f, -100.f, -640.f
};
GLubyte colorData[4*3] =
{
200, 200, 200,
200, 200, 200,
200, 200, 200,
200, 200, 200
};
GLubyte texCoords[4*2] =
{
0, 0,
1, 0,
1, 1,
0, 1
};
GLuint indexList[2][3] =
{
{0, 1, 2}, // first triangle
{0, 2, 3} // second triangle
};
glGenBuffers(1, &vbo_floor_pos);
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_pos);
glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), vertexData, GL_STATIC_DRAW);
glGenBuffers(1, &vbo_floor_color);
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_color);
glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(GLubyte), colorData, GL_STATIC_DRAW);
glGenBuffers(1, &vbo_floor_tex);
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_tex);
glBufferData(GL_ARRAY_BUFFER, 4*2 * sizeof(float), texCoords, GL_STATIC_DRAW);
glGenBuffers(1, &ebo_floor);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2*3 * sizeof(GLuint), indexList, GL_STATIC_DRAW);
glGenVertexArrays( 1, &vao_floor );
glBindVertexArray(vao_floor);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);
glEnableVertexAttribArray(0); // position
glEnableVertexAttribArray(1); // color
glEnableVertexAttribArray(2); // texture coords
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_pos);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_color);
glVertexAttribPointer( 1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL );
glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_tex);
glVertexAttribPointer( 2, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, NULL );
glBindVertexArray(0);
}
Отрисовка пола
void drawFloor()
{
prog_use(&floorsh);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glBindVertexArray(vao_floor);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glDisable(GL_TEXTURE_2D);
}
Инициализация левой и правой стены
/* left wall */
static float left_wall[12] = {-100.f, -100.f, -320.f,
-100.f, -100.f, -640.f,
-100.f, 100.f, -640.f,
-100.f, 100.f, -320.f };
static float left_normal[3] = {1.f, 0.f, 0.f};
static float left_color[3] = {165, 165, 165};
static struct PLANE left;
/* right wall */
static float right_wall[12] = { 100.f, -100.f, -320.f,
100.f, 100.f, -320.f,
100.f, 100.f, -640.f,
100.f, -100.f, -640.f };
static float right_normal[3] = {-1.f, 0.f, 0.f};
static float right_color[3] = {165, 165, 165};
static struct PLANE right;
void plane_init(PLANE *plane, const float *points, float *normal, float *color)
{
float vertexData[4*3]=
{
points[0], points[ 1], points[ 2],
points[3], points[ 4], points[ 5],
points[6], points[ 7], points[ 8],
points[9], points[10], points[11]
};
GLubyte colorData[4*3] =
{
color[0], color[1], color[2],
color[0], color[1], color[2],
color[0], color[1], color[2],
color[0], color[1], color[2]
};
GLubyte texCoords[4*2] =
{
0, 0,
1, 0,
1, 1,
0, 1
};
GLubyte normalData[4*3] =
{
normal[0], normal[1], normal[2],
normal[0], normal[1], normal[2],
normal[0], normal[1], normal[2],
normal[0], normal[1], normal[2]
};
GLuint indexList[2][3] =
{
{0, 1, 2}, // first triangle
{0, 2, 3} // second triangle
};
glGenBuffers(1, &plane->vbo_pos);
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_pos);
glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), vertexData, GL_STATIC_DRAW);
glGenBuffers(1, &plane->vbo_color);
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_color);
glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(GLubyte), colorData, GL_STATIC_DRAW);
glGenBuffers(1, &plane->vbo_tex);
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_tex);
glBufferData(GL_ARRAY_BUFFER, 4*2 * sizeof(float), texCoords, GL_STATIC_DRAW);
glGenBuffers(1, &plane->vbo_normal);
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_normal);
glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), normalData, GL_STATIC_DRAW);
glGenBuffers(1, &plane->ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2*3 * sizeof(GLuint), indexList, GL_STATIC_DRAW);
glGenVertexArrays( 1, &plane->vao );
glBindVertexArray(plane->vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);
glEnableVertexAttribArray(0); // position
glEnableVertexAttribArray(1); // color
glEnableVertexAttribArray(2); // texture coords
glEnableVertexAttribArray(3); // normal
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_pos);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_color);
glVertexAttribPointer( 1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL );
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_tex);
glVertexAttribPointer( 2, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, NULL );
glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_normal);
glVertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, 0, NULL );
glBindVertexArray(0);
}
void plane_draw(PLANE *plane)
{
glBindVertexArray(plane->vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
Инициализация шейдеров:
void init_scene()
{
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
glClearColor(0.5f, 0.5f, 0.5f, 1.0f );
prog_create(&floorsh);
prog_attach_shader_from_file(&floorsh, FLOOR_VERTEX_SHADER_NAME);
prog_attach_shader_from_file(&floorsh, FLOOR_FRAGMENT_SHADER_NAME);
prog_link(&floorsh);
prog_use(&floorsh);
initFloor();
prog_create(&wallsh);
prog_attach_shader_from_file(&wallsh, WALL_VERTEX_SHADER_NAME);
prog_attach_shader_from_file(&wallsh, WALL_FRAGMENT_SHADER_NAME);
prog_link(&wallsh);
prog_use(&wallsh);
initWalls();
prog_set_uniform_3f(&wallsh, "lightSource.ambient", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "lightSource.diffuse", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "lightSource.specular", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "lightSource.position", 50.f, 50.f, -320.f);
prog_set_uniform_3f(&wallsh, "lightModel.ambient", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "material.emission", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "material.ambient", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "material.diffuse", 1.0f, 1.0f, 1.0f);
prog_set_uniform_3f(&wallsh, "material.specular", 1.0f, 1.0f, 1.0f);
prog_set_uniform_float(&wallsh, "material.shininess", 10.0f);
mat4_identity(&model);
mat4_identity(&view);
MAT4 MV;
mat4_multiply(&MV, &view, &model);
prog_set_uniform_mat4(&wallsh, "modelViewMatrix", &MV);
MAT3 NormalMatrix;
NormalMatrix.M[0] = MV.M[0]; NormalMatrix.M[3] = MV.M[4]; NormalMatrix.M[6] = MV.M[8];
NormalMatrix.M[1] = MV.M[1]; NormalMatrix.M[4] = MV.M[5]; NormalMatrix.M[7] = MV.M[9];
NormalMatrix.M[2] = MV.M[2]; NormalMatrix.M[5] = MV.M[6]; NormalMatrix.M[8] = MV.M[10];
prog_set_uniform_mat3(&wallsh,"normalMatrix", &NormalMatrix);
mat4_perspective_projection(&projection, -FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, FRUSTNEAR, FRUSTFAR);
prog_set_uniform_mat4(&wallsh, "projectionMatrix", &projection);
glEnable(GL_DEPTH_TEST);
//glPolygonMode(GL_FRONT, GL_FILL);
//glCullFace(GL_BACK);
CHECK_GL_ERROR();
}
Заранее благодарю за осмысленные ответы и помощь!